Hibernate框架筆記04HQL_QBC查詢詳解_抓取策略優化機制
阿新 • • 發佈:2019-04-25
新項目 long ini title 右外連接 int 方式 set 不包含
目錄
- 1. Hibernate的查詢方式
- 1.1 方式一:OID查詢
- 1.2 方式二:對象導航查詢
- 1.3 方式三:HQL方式
- 1.4 方式四:QBC查詢
- 1.5 方式五:SQL查詢
- 2. 環境搭建
- 3. HQL查詢
- 3.1 簡單查詢
- 3.2 別名查詢
- 3.3 排序查詢
- 3.4 條件查詢
- 3.4 投影查詢
- 3.5 分頁查詢
- 3.6 分組統計查詢
- 3.7 HQL的多表查詢
- 3.7.1 SQL的多表查詢
- 3.7.2 HQL的多表查詢
- 4. QBC查詢
- 4.1 簡單查詢
- 4.2 排序查詢
- 4.3 分頁查詢
- 4.4 條件查詢
- 4.5 統計查詢
- 4.6 離線條件查詢(***)DetachedCriteria
- 5. SQL查詢
- 6. Hibernate的抓取策略
- 6.1 延遲加載的概述
- 6.1.1 什麽是延遲加載
- 6.1.2 延遲加載的分類
- 6.2 抓取策略
- 6.2.1 抓取策略概述
- 6.2.2 set上的fetch和lazy
- 6.2.3 many-to-one上的fetch和lazy
- 6.2.4 批量抓取
- 6.1 延遲加載的概述
1. Hibernate的查詢方式
- 在Hibernate中提供了5種查詢方式。
1.1 方式一:OID查詢
- OID查詢:Hibernate根據對象的
OID(主鍵)
進行檢索。 - 使用
get()
方法Customer customer = session.get(Customer.class,1L);
- 使用
load()
方法Customer customer = session.load(Custoemr.class,1L);
1.2 方式二:對象導航查詢
對象導航檢索:Hibernate根據一個已經查詢到的對象,獲得其關聯的對象的一種查詢方式。
LinkMan linkMan = session.get(LinkMan.class,1L); Customer customer = linkMan.getCustomer(); Customer customer = session.get(Customer.class,2L); Set<LinkMan> linkMans = customer.getLinkMans();
1.3 方式三:HQL方式
- HQL查詢:
Hibernate Query Language
,Hibernate的查詢語言,是一種面向對象的方式的查詢語言,語法類似SQL。通過session.createQuery()
,接收一個HQL進行查詢方式。
1.4 方式四:QBC查詢
- QBC查詢:
Query By Criteria
,條件查詢。是一種更加面向對象化的查詢方式。
1.5 方式五:SQL查詢
- SQL查詢:通過使用SQL語句進行查詢。
2. 環境搭建
創建一個新項目,導入相關jar包
新建數據庫,新建數據表,分別為cst_custoemr和cst_linkman
- 新建兩個實體,分別為Customer和LinkMan
- Customer中生成
toString
方法,不包含LinkMan - LinkMan中生成
toString
方法,不包含Customer
- Customer中生成
準備工具類,配置文件,映射文件
生成測試的數據,該方法執行3次
/** * HQL的查詢方式的測試類 * @author itzhouq * */ public class HibernateDemo1 { @Test public void test1() { Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); Customer customer = new Customer(); customer.setCust_name("莫爾德"); for (int i = 0; i < 10; i++) { LinkMan linkMan = new LinkMan(); linkMan.setLkm_name("老馬"+i); customer.getLinkMans().add(linkMan); session.save(linkMan); } session.save(customer); transaction.commit(); } }
3. HQL查詢
3.1 簡單查詢
@Test
public void test2() {//HQL的簡單查詢
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 簡單查詢
Query query = session.createQuery("from Customer");
List<Customer> list = query.list();
// sql中支持*號的寫法:select * from cst_customer;但是在HQL中不支持*號的寫法。
// Query query2 = session.createQuery("select * from from Customer");// 報錯
// List<Customer> list2 = query.list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
}
3.2 別名查詢
@Test
public void test3() {// 別名查詢
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 別名查詢
// Query query = session.createQuery("from Customer c");
// List<Customer> list = query.list();
Query query = session.createQuery("select c from Customer c");
List<Customer> list = query.list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
}
3.3 排序查詢
@Test
public void test5() {// 排序查詢
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 排序查詢
// 默認情況
//List<Customer> list = session.createQuery("from Customer order by cust_id").list();
// 設置兼降序排序 升序使用asc 降序使用desc
List<Customer> list = session.createQuery("from Customer order by cust_id desc").list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
}
3.4 條件查詢
@Test
public void test4() {// 排序查詢
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 排序查詢
// 1. 按位置綁定:根據參數的位置進行綁定
// 一個條件
// Query query = session.createQuery("from Customer where cust_name = ?");
// query.setParameter(0, "朱元璋");
// 多個條件
// Query query = session.createQuery("from Customer where cust_source = ? and cust_name like ?");
// query.setParameter(0, "朋友推薦");
// query.setParameter(1, "朱%");
// 2. 按名稱綁定
Query query = session.createQuery("from Customer where cust_source = :aaa and cust_name like :bbb");
// 設置參數:
query.setParameter("aaa", "朋友推薦");
query.setParameter("bbb", "朱%");
List<Customer> list = query.list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
}
3.4 投影查詢
- 投影查詢:查詢對象的某個或某些屬性
@Test
public void test6() {// 投影查詢
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 投影查詢
// 單個屬性
// List<Object> list = session.createQuery("select c.cust_name from Customer c").list();
// for (Object customer : list) {
// System.out.println(customer);
//
// }
// 多個屬性:
// List<Object[]> list = session.createQuery("select c.cust_name,c.cust_source from Customer c").list();
// for (Object[] objects : list) {
// System.out.println(Arrays.toString(objects));
// }
// 查詢多個屬性,但我想封裝到對象中-----需要這兩個參數的構造函數
List<Object[]> list = session.createQuery("select c.cust_name,c.cust_source from Customer c").list();
for (Object[] customer : list) {
System.out.println(Arrays.toString(customer));
}
transaction.commit();
}
3.5 分頁查詢
@Test
public void test7() {// 分頁查詢
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 分頁查詢
Query query = session.createQuery("from LinkMan");
query.setFirstResult(20);
query.setMaxResults(5);
List<LinkMan> list = query.list();
for (LinkMan linkMan : list) {
System.out.println(linkMan);
}
transaction.commit();
}
3.6 分組統計查詢
@Test
public void test8() {// 分組統計查詢
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 分組統計查詢
Object object = session.createQuery("select count(*) from Customer").uniqueResult();
System.out.println(object);
//分組統計:
Query query = session.createQuery("select cust_source,count(*) from Customer group by cust_source");
List<Object[]> list = query.list();
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}
transaction.commit();
}
3.7 HQL的多表查詢
3.7.1 SQL的多表查詢
- 連接查詢
- 交叉連接:笛卡爾積
- 內連接:
innner join(inner可以省略)
- 隱式內連接:
select * from A,B where A.id = B.aid;
- 顯式內連接:
select * from A inner join B on A.id = B.aid;
- 隱式內連接:
- 外連接:
outer可以省略
- 左外連接:
select * from A left outer join B on A.id = B.id;
- 右外連接:
select * from A right outerjoin B on A.id = B.id;
- 左外連接:
- 子查詢
3.7.2 HQL的多表查詢
- 連接查詢
- 交叉連接
- 內連接:
- 顯式內連接
- 隱式內連接
- 迫切內連接
- 外連接:
- 左外連接
- 右外連接
- 迫切左外連接
@Test
public void test7() { // 多表查詢
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
// SQL:select * from cst_customer c inner join cst_linkman l on c.cust_id = l.lkm_cust_id
// HQL:內連接from Customer c inner join c.linkMans
// 內連接得到的是一個數組
// List<Object[]> list = session.createQuery("from Customer c inner join c.linkMans").list();
// for (Object[] objects : list) {
// System.out.println(Arrays.toString(objects));
// }
// HQL:迫切內連接,其實就是在普通的內連接inner join後添加一個關鍵字fetch.
// 迫切內連接的到的是一個對象,在Customer的toString中給定LinkMans可以得到全部字段
List<Customer> list2 = session.createQuery("select distinct c from Customer c inner join fetch c.linkMans").list();
for (Customer customer : list2) {
System.out.println(customer);
}
transaction.commit();
}
4. QBC查詢
4.1 簡單查詢
@Test
public void test1() { // 簡單查詢
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
//獲得Criteria的對象
Criteria criteria = session.createCriteria(Customer.class);
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
}
4.2 排序查詢
@Test
public void test2() { // 排序查詢
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
//獲得Criteria的對象
Criteria criteria = session.createCriteria(Customer.class);
// criteria.addOrder(Order.desc("cust_id")); // 降序
criteria.addOrder(Order.asc("cust_id")); // 升序
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
}
4.3 分頁查詢
@Test
public void test3() { // 分頁查詢
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
//獲得Criteria的對象
Criteria criteria = session.createCriteria(LinkMan.class);
criteria.setFirstResult(20);
criteria.setMaxResults(5);
List<LinkMan> list = criteria.list();
for (LinkMan linkMan : list) {
System.out.println(linkMan);
}
transaction.commit();
}
4.4 條件查詢
@Test
public void test4() { // 條件查詢
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
//獲得Criteria的對象
Criteria criteria = session.createCriteria(Customer.class);
// 設置條件
/*
* = eq
* > gt
* >= ge
* < lt
* <= le
* <> ne
* like
* in
* and
* or
*/
criteria.add(Restrictions.eq("cust_source", "小廣告"));
criteria.add(Restrictions.like("cust_name", "李%"));
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
}
4.5 統計查詢
@Test
public void test5() { // 條件查詢
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
//獲得Criteria的對象
Criteria criteria = session.createCriteria(Customer.class);
/**
* add :普通的條件。where後面條件
* addOrder:排序
* setProjecttion:聚合函數和group by having
*/
criteria.setProjection(Projections.rowCount());
Long num = (Long) criteria.uniqueResult();
System.out.println(num);
transaction.commit();
}
4.6 離線條件查詢(***)DetachedCriteria
離線條件查詢在前臺需要傳遞多個條件,用於篩選的時候很方便,可以不用在dao層拼接字符串
代碼
@Test
public void test6() { // 離線條件查詢
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Customer.class);
detachedCriteria.add(Restrictions.like("cust_name", "李%"));
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
Criteria criteria = detachedCriteria.getExecutableCriteria(session);
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
}
5. SQL查詢
@Test
public void test1() {
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 調用的createSQLQuery,返回的值遍歷後是數組形式的集合
// SQLQuery sqlQuery = session.createSQLQuery("select * from cst_customer");
// List<Object[]> list = sqlQuery.list();
// for (Object[] objects : list) {
// System.out.println(Arrays.toString(objects));
// }
SQLQuery sqlQuery = session.createSQLQuery("select * from cst_customer");
sqlQuery.addEntity(Customer.class); //封裝到實體Customer中
List<Customer> list = sqlQuery.list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
}
6. Hibernate的抓取策略
6.1 延遲加載的概述
6.1.1 什麽是延遲加載
- 延遲加載:lazy(懶加載)。執行到該行代碼的時候,不會發送語句去進行查詢,在真正使用這個對象的屬性的時候才會發送SQL語句進行查詢。
6.1.2 延遲加載的分類
類級別的延遲加載
- 指的是通過load方法查詢某個對象的時候,是否采用延遲加載。
session.load(Customer.class,1L);
- 類級別的延遲加載通過
<class>
上的lazy進行配置。讓lazy失效的方法有:- 將lazy設置為false
- 將持久化類使用final修改
Hibernate.ininialize()
- 指的是通過load方法查詢某個對象的時候,是否采用延遲加載。
關聯級別的延遲加載
指的是在查詢到某個對象的時候,查詢其關聯對象的時候,是否采用延遲加載。
Customer customer = session.get(Customer.class,1L); customer.getLinkMans(); //通過客戶獲得聯系人的時候,聯系人對象是否采用了延遲記載,稱為關聯級別的延遲加載。
抓取策略往往會和關聯級別的延遲加載一起使用,優化語句。
6.2 抓取策略
Customer.hbm.xml
<set name="linkMans" fetch="select" lazy="true">
<!-- column多的一方的外鍵的名稱 -->
<key column="lkm_cust_id"></key>
<!-- class:多的一方的類的全限定名 -->
<one-to-many class="com.itzhouq.hibernate.domain.LinkMan"/>
</set>
6.2.1 抓取策略概述
- 通過一個對象抓取到關聯對象需要發送SQL語句,SQL語句如何發送,發送成什麽樣格式?這些可以通過策略進行配置。
- 通過
<set>
或者<many-to-one>
上的fetch屬性進行配置 - fetch和這些標簽上的lazy如何設置,優化發送的SQL語句。
- 通過
6.2.2 set上的fetch和lazy
- fetch:抓取策略,控制SQL語句格式
- select:默認值,發送普通的select語句,查詢關聯對象。
- join:發送一條迫切左外連接查詢關聯對象。
- subeselect:發送一條子查詢查詢其關聯對象。
- lazy:延遲加載,控制查詢關聯對象的時候是否采用延遲加載
- true:默認值,查詢關聯對象的時候,采用延遲加載
- false:查詢關聯對象的時候,不采用延遲加載
- extra:及其懶惰。
- 實際開發過程中,一般采用默認值。如果有特殊需求,可能需要配置join。
6.2.3 many-to-one上的fetch和lazy
- fetch:抓取策略,控制SQL語句格式
- select:默認值,發送普通的select語句,查詢關聯對象。
- join:發送一條迫切左外連接
- lazy:延遲加載,控制查詢關聯對象的時候是否采用延遲加載
- proxy:默認值,proxy具體的取值,取決於另一端的class上的lazy的值。
- false:查詢關聯對象,不采用延遲。
- no-proxy:不用
- 在實際開發過程中,一般采用默認值。如果有特殊的需求,可能需要配置join。
6.2.4 批量抓取
一批關聯對象一起抓取,betch-size。
package com.itzhouq.hibernate.demo; import java.util.List; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Test; import com.itzhouq.hibernate.domain.Customer; import com.itzhouq.hibernate.domain.LinkMan; import com.itzhouq.hibernate.utils.HibernateUtils; /* * 批量抓取測試 */ public class HibernateDemo4 { @Test public void test1() { // 獲取客戶的時候,批量抓取聯系人 // 在Customer.hbm.xml中set上配置batch-size Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); List<Customer> list = session.createQuery("from Customer").list(); for (Customer customer : list) { System.out.println(customer.getCust_name()); for (LinkMan linkMan : customer.getLinkMans()) { System.out.println(linkMan.getLkm_name()); } } transaction.commit(); } }
<set name="linkMans" batch-size="5"> <!-- column多的一方的外鍵的名稱 --> <key column="lkm_cust_id"></key> <!-- class:多的一方的類的全限定名 --> <one-to-many class="com.itzhouq.hibernate.domain.LinkMan"/> </set>
Hibernate框架筆記04HQL_QBC查詢詳解_抓取策略優化機制