Hibernate第四天:Hibernate的查詢方式、抓取策略
目錄
1.4.6離線條件查詢(SSH)---DetachedCriteria
1Hibernate的查詢的方式
在Hibernate中提供了很多種的查詢的方式。Hibernate共提供了五種查詢方式。
1.1Hibernate的查詢方式:OID查詢
OID檢索:Hibernate根據物件的OID(主鍵)進行檢索。
1.1.1使用get方法
Customer customer = session.get(Customer.class,1l);
1.1.2使用load方法
Customer customer = session.load(Customer.class,1l);
1.2Hibernate的查詢方式:物件導航檢索
物件導航檢索: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.3Hibernate的查詢方式:HQL檢索
HQL查詢:Hibernate Query Language,Hibernate的查詢語言,是一種面向物件的方式的查詢語言,語法類似SQL。通過session.createQuery(),用於接收一個HQL進行查詢方式。
1.3.1初始化一些資料
@Test
/**
* 初始化資料
*/
public void demo1() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 建立一個客戶
Customer customer = new Customer();
customer.setCust_name("張帥");
for (int i = 1; i <= 10; i++) {
LinkMan linkMan = new LinkMan();
linkMan.setLkm_name("王曉丹" + i);
linkMan.setCustomer(customer);
customer.getLinkMans().add(linkMan);
session.save(linkMan);
}
session.save(customer);
tx.commit();
}
1.3.2HQL的簡單查詢
@Test
/**
* HQL的簡單查詢
*/
public void demo2() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 簡單的查詢
Query query = session.createQuery("from Customer");
List<Customer> list = query.list();
// sql中支援*號的寫法:select * from cst_customer; 但是在HQL中不支援*號的寫法。
/*
* Query query = session.createQuery("select * from Customer");// 報錯
* List<Customer> list = query.list();
*/
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
}
1.3.3HQL的別名查詢
@Test
/**
* 別名查詢
*/
public void demo3() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = 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);
}
tx.commit();
}
1.3.4HQL的排序查詢
@Test
/**
* 排序查詢
*/
public void demo4() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = 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);
}
tx.commit();
}
1.3.5HQL的條件查詢
@Test
/**
* 條件查詢
*/
public void demo5() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 條件的查詢
// 一、按位置繫結:根據引數的位置進行繫結。
// 一個條件
/*
* Query query = session.createQuery("from Customer where cust_name = ?"
* ); query.setParameter(0, "李兵"); List<Customer> list = query.list();
*/
// 多個條件
/*
* Query query = session.createQuery(
* "from Customer where cust_source = ? and cust_name like ?");
* query.setParameter(0, "小廣告"); query.setParameter(1, "李%");
* List<Customer> list = query.list();
*/
// 二、按名稱繫結
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);
}
tx.commit();
}
1.3.6HQL的投影查詢
投影查詢:查詢物件的某個或某些屬性。
@Test
/**
* 投影查詢
*/
public void demo6() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 投影查詢
// 單個屬性
/*
* List<Object> list = session.createQuery(
* "select c.cust_name from Customer c").list(); for (Object object :
* list) { System.out.println(object); }
*/
// 多個屬性:
/*
* 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<Customer> list = session.createQuery("select new Customer(cust_name,cust_source) from Customer").list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
}
1.3.7HQL的分頁查詢
@Test
/**
* 分頁查詢
*/
public void demo7() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 分頁查詢
Query query = session.createQuery("from LinkMan");
query.setFirstResult(20);
query.setMaxResults(10);
List<LinkMan> list = query.list();
for (LinkMan linkMan : list) {
System.out.println(linkMan);
}
tx.commit();
}
1.3.8HQL的分組統計查詢
@Test
/**
* 分組統計查詢
*/
public void demo8() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 聚合函式的使用:count(),max(),min(),avg(),sum()
Object object = session.createQuery("select count(*) from Customer").uniqueResult();
System.out.println(object);
// 分組統計:
List<Object[]> list = session.createQuery("select cust_source,count(*) from Customer group by cust_source").list();
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}
tx.commit();
}
1.3.9HQL的多表查詢
- SQL的多表查詢
- 連線查詢
- 交叉連線:笛卡爾積
- 連線查詢
select * from A,B;
-
-
- 內連線 :inner join (inner 可以省略)
- 隱式內連線:
- 內連線 :inner join (inner 可以省略)
-
select * from A,B where A.id = B.aid;
-
-
-
- 顯示內連線:
-
-
select * from A inner join B on A.id = B.aid;
-
-
- 外連線 :
- 左外連線:left outer join(outer 可以省略)
- 外連線 :
-
select * from A left outer join B on A.id= B.aid;
-
-
-
- 右外連線:right outer join(outer 可以省略)
-
-
select * from A right outer join B on A.id = B.aid;
-
- 子查詢
- HQL的多表查詢
- 連線查詢
- 交叉連線
- 內連線
- 顯示內連線
- 隱式內連線
- 迫切內連線
- 外連線
- 左外連線
- 右外連線
- 迫切左外連線
- 連線查詢
@Test
/**
* HQL的多表查詢
*/
public void demo9() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = 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. from Customer c inner
// join fetch c.linkMans
List<Customer> list = session.createQuery("select distinct c from Customer c inner join fetch c.linkMans").list();// 通知hibernate,將另一個物件的資料封裝到該物件中
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
}
1.4Hibernate的查詢方式:QBC檢索
QBC查詢:Query By Criteria,條件查詢。是一種更加面向物件化的查詢的方式。
1.4.1簡單查詢
@Test
/**
* 簡單的查詢
*/
public void demo1(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 獲得Criteria的物件
Criteria criteria = session.createCriteria(Customer.class);
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
}
1.4.2排序查詢
@Test
/**
* 排序查詢
*/
public void demo2(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 排序查詢
Criteria criteria = session.createCriteria(Customer.class);
// criteria.addOrder(Order.asc("cust_id")); // 升序
criteria.addOrder(Order.desc("cust_id")); // 降序
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
}
1.4.3分頁查詢
@Test
/**
* 分頁查詢
*/
public void demo3(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 分頁查詢
Criteria criteria = session.createCriteria(LinkMan.class);
criteria.setFirstResult(10);
criteria.setMaxResults(10);
List<LinkMan> list = criteria.list();
for (LinkMan linkMan : list) {
System.out.println(linkMan);
}
tx.commit();
}
1.4.4條件查詢
@Test
/**
* 條件查詢
*/
public void demo4(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 條件查詢
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.or(Restrictions.like("cust_name", "李%")));
criteria.add(Restrictions.like("cust_name", "李%"));
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
}
1.4.5統計查詢
@Test
/**
* 統計查詢
*/
public void demo5(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(Customer.class);
/**
* add :普通的條件。where後面條件
* addOrder :排序
* setProjection :聚合函式 和 group by having
*/
criteria.setProjection(Projections.rowCount());
Long num = (Long) criteria.uniqueResult();
System.out.println(num);
tx.commit();
}
1.4.6離線條件查詢(SSH)---DetachedCriteria
@Test
/**
* 離線條件查詢
*/
public void demo6(){
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();
}
1.5Hibernate的查詢方式:SQL檢索
SQL查詢
SQL查詢:通過使用sql語句進行查詢
package top.yangxianyang.demo1;
import java.util.Arrays;
import java.util.List;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import top.yangxianyang.entity.Customer;
import top.yangxianyang.utils.HibernateUtils;
/**
* SQL查詢
* @author yxy
*
*/
public class HibernateTest3 {
@Test
public void demo1(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
/*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);
List<Customer> list = sqlQuery.list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
}
}
2Hibernate的抓取策略(優化)
2.1延遲載入的概述
2.1.1什麼是延遲載入
延遲載入:lazy(懶載入)。執行到該行程式碼的時候,不會發送語句去進行查詢,在真正使用這個物件的屬性的時候才會傳送SQL語句進行查詢。
2.1.2延遲載入的分類
- 類級別的延遲載入
- 指的是通過load方法查詢某個物件的時候,是否採用延遲。session.load(Customer.class,1l);
- 類級別延遲載入通過<class>上的lazy進行配置,如果讓lazy失效
- 將lazy設定為false
- 將持久化類使用final修飾
- Hibernate. Initialize()
package top.yangxianyang.demo1;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import top.yangxianyang.entity.Customer;
import top.yangxianyang.utils.HibernateUtils;
/**
* Hibernate的延遲載入
* @author yxy
*
*/
public class HibernateTest4 {
@Test
/**
* 類級別的延遲載入
* * 在<class>的標籤上配置的lazy
*/
public void demo1(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
Customer customer = session.load(Customer.class, 1l);
Hibernate.initialize(customer);
System.out.println(customer);
tx.commit();
}
}
- 關聯級別的延遲載入
- 指的是在查詢到某個物件的時候,查詢其關聯的物件的時候,是否採用延遲載入。
Customer customer = session.get(Customer.class,1l);
customer.getLinkMans();----通過客戶獲得聯絡人的時候,聯絡人物件是否採用了延遲載入,稱為是關聯級別的延遲。
-
- 抓取策略往往會和關聯級別的延遲載入一起使用,優化語句。
2.2抓取策略
2.2.1抓取策略的概述
- 通過一個物件抓取到關聯物件需要傳送SQL語句,SQL語句如何傳送,傳送成什麼樣格式通過策略進行配置。
- 通 過<set>或者<many-to-one>上通過fetch屬性進行設定
- fetch和這些標籤上的lazy如何設定優化傳送的SQL語句
2.2.2<set>上的fetch和lazy
- fetch:抓取策略,控制SQL語句格式
- select :預設值,傳送普通的select語句,查詢關聯物件
- join :傳送一條迫切左外連線查詢關聯物件
- subselect :傳送一條子查詢查詢其關聯物件
- lazy:延遲載入,控制查詢關聯物件的時候是否採用延遲
- true :預設值,查詢關聯物件的時候,採用延遲載入
- false :查詢關聯物件的時候,不採用延遲載入
- extra :及其懶惰。
- 在實際開發中,一般都採用預設值。如果有特殊的需求,可能需要配置join。
package top.yangxianyang.demo1;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import top.yangxianyang.entity.Customer;
import top.yangxianyang.entity.LinkMan;
import top.yangxianyang.utils.HibernateUtils;
/**
* 在<set>上的fetch和lazy
* @author yxy
*
*/
public class HibernateTest5 {
@Test
/**
* 預設情況:
*/
public void demo1(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 查詢1號客戶
Customer customer = session.get(Customer.class, 1l);// 傳送一條查詢客戶的SQL
System.out.println(customer.getCust_name());
// 檢視1號客戶的每個聯絡人的資訊
for (LinkMan linkMan : customer.getLinkMans()) {// 傳送一條根據客戶ID查詢聯絡人的SQL
System.out.println(linkMan.getLkm_name());
}
tx.commit();
}
@Test
/**
* 設定fetch="select" lazy="true"
*/
public void demo2(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 查詢1號客戶
Customer customer = session.get(Customer.class, 1l);// 傳送一條查詢客戶的SQL
System.out.println(customer.getCust_name());
// 檢視1號客戶的每個聯絡人的資訊
for (LinkMan linkMan : customer.getLinkMans()) {// 傳送一條根據客戶ID查詢聯絡人的SQL
System.out.println(linkMan.getLkm_name());
}
tx.commit();
}
@Test
/**
* 設定 fetch="select" lazy="false"
*/
public void demo3(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 查詢1號客戶
Customer customer = session.get(Customer.class, 1l);// 傳送兩條SQL語句:查詢客戶的名稱,查詢客戶關聯聯絡人
System.out.println(customer.getCust_name());
/*// 檢視1號客戶的每個聯絡人的資訊
for (LinkMan linkMan : customer.getLinkMans()) {//
System.out.println(linkMan.getLkm_name());
}*/
System.out.println(customer.getLinkMans().size());
tx.commit();
}
@Test
/**
* 設定fetch="select" lazy="extra"
*/
public void demo4(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 查詢1號客戶
Customer customer = session.get(Customer.class, 1l);// 傳送一條查詢1號客戶的SQL語句
System.out.println(customer.getCust_name());
System.out.println(customer.getLinkMans().size());// 傳送一條select count() from ...;
tx.commit();
}
@Test
/**
* 設定fetch="join" lazy=失效
*/
public void demo5(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
// 查詢1號客戶
Customer customer = session.get(Customer.class, 1l);// 傳送一條迫切左外連線查詢記錄
System.out.println(customer.getCust_name());
System.out.println(customer.getLinkMans().size());// 不傳送
tx.commit();
}
@SuppressWarnings("unchecked")
@Test
/**
* 設定fetch="subselect" lazy="true"
*/
public void demo6(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
List<Customer> list = session.createQuery("from Customer").list();// 傳送查詢所有客戶的SQL
for (Customer customer : list) {
System.out.println(customer.getCust_name());
System.out.println(customer.getLinkMans().size());// 傳送一條子查詢
}
tx.commit();
}
@SuppressWarnings("unchecked")
@Test
/**
* 設定fetch="subselect" lazy="false"
*/
public void demo7(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
List<Customer> list = session.createQuery("from Customer").list();// 傳送查詢所有客戶的SQL,傳送一條子查詢
for (Customer customer : list) {
System.out.println(customer.getCust_name());
System.out.println(customer.getLinkMans().size());//
}
tx.commit();
}
}
2.2.3<many-to-one>上的fetch和lazy
- fetch :抓取策略,控制SQL語句格式。
- select :預設值,傳送普通的select語句,查詢關聯物件。
- join :傳送一條迫切左外連線。
- lazy :延遲載入,控制查詢關聯物件的時候是否採用延遲。
- proxy :預設值,proxy具體的取值,取決於另一端的<class>上的lazy的值。
- false :查詢關聯物件,不採用延遲。
- no-proxy :(不會使用)
- 在實際開發中,一般都採用預設值。如果有特殊的需求,可能需要配置join。
package top.yangxianyang.demo1;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import top.yangxianyang.entity.LinkMan;
import top.yangxianyang.utils.HibernateUtils;
/**
* many-to-one上的fetch和lazy測試
* @author yxy
*
*/
public class HibernateTest6 {
@Test
/**
* 預設值
*/
public void demo1(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
LinkMan linkMan = session.get(LinkMan.class, 1l);// 傳送一條查詢聯絡人語句
System.out.println(linkMan.getLkm_name());
System.out.println(linkMan.getCustomer().getCust_name());// 傳送一條select語句查詢聯絡人所關聯的客戶
tx.commit();
}
@Test
/**
* fetch="select" lazy="proxy"
*/
public void demo2(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
LinkMan linkMan = session.get(LinkMan.class, 1l);// 傳送一條查詢聯絡人語句
System.out.println(linkMan.getLkm_name());
System.out.println(linkMan.getCustomer().getCust_name());// 傳送一條select語句查詢聯絡人所關聯的客戶
tx.commit();
}
@Test
/**
* fetch="select" lazy="false"
*/
public void demo3(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
LinkMan linkMan = session.get(LinkMan.class, 1l);// 傳送一條查詢聯絡人語句,傳送一條select語句查詢聯絡人所關聯的客戶
System.out.println(linkMan.getLkm_name());
System.out.println(linkMan.getCustomer().getCust_name());//
tx.commit();
}
@Test
/**
* fetch="join" lazy=失效
*/
public void demo4(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
LinkMan linkMan = session.get(LinkMan.class, 1l);// 傳送一條迫切左外連線查詢聯絡人所關聯的客戶。
System.out.println(linkMan.getLkm_name());
System.out.println(linkMan.getCustomer().getCust_name());//
tx.commit();
}
}
2.3批量抓取
2.3.1什麼是批量抓取
一批關聯物件一起抓取,batch-size
2.3.2測試批量抓取
package top.yangxianyang.demo1;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import top.yangxianyang.entity.Customer;
import top.yangxianyang.entity.LinkMan;
import top.yangxianyang.utils.HibernateUtils;
/**
* 批量抓取
* @author yxy
*
*/
public class HibernateTest7 {
@SuppressWarnings("unchecked")
@Test
/**
* 獲取客戶的時候,批量抓取聯絡人
* 在Customer.hbm.xml中set上配置batch-size
*/
public void demo1(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = 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());
}
}
tx.commit();
}
@SuppressWarnings("unchecked")
@Test
/**
* 獲取聯絡人的時候,批量抓取客戶
* * 在Customer.hbm.xml中<class>上配置
*/
public void demo2(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
List<LinkMan> list = session.createQuery("from LinkMan").list();
for (LinkMan linkMan : list) {
System.out.println(linkMan.getLkm_name());
System.out.println(linkMan.getCustomer().getCust_name());
}
tx.commit();
}
}
原始碼連結:
連結: https://pan.baidu.com/s/1FP2wVYkUJBjVqmHkGiP7og 提取碼: aaeh