day29HibernateDay04(HQL/SQL/QBC查詢lazy和fetch 懶載入)
阿新 • • 發佈:2018-11-29
回顧 1、一對多關聯關係對映 JavaBean的編寫 編寫對映的配置檔案 使用級聯儲存、刪除、孤兒刪除,使用cascade="save-update,delete,delte-orphan" 放棄外來鍵的維護的權力,使用inverse="true" 2、多對多關聯關係對映 儲存,必須放棄外來鍵的維護的權力 框架的查詢方式 1、唯一標識OID的檢索方式 session.get(物件.class,OID) 2、物件的導航的方式 new User().getRole().getRname() Customer.getLinkmans() 先獲取顧客通過顧客獲取聯絡人的id然後查詢聯絡人的表獲得聯絡人 3、HQL的檢索方式 Hibernate Query Language Hibernate的查詢語言 4、QBC的檢索方式 Query By Criteria 條件查詢 5、SQL檢索方式 本地的SQL檢索 HQL查詢方式概述 1、HQL的介紹 HQL(Hibernate Query Language)是面向物件的查詢語言,和SQL查詢語言有些相似 在Hibernate提供的各種檢索方式中,HQL是使用最廣的檢索方式 2、HQL和SQL的關係 SQL查詢語言是面向物件的。Hibernate負責解析HQL查詢語句,然後根據物件-關係對映檔案中的對映資訊,把HQL查詢語句翻譯成相應的SQL語句 HQL查詢語句的主體是域模型中的類及類的屬性 SQL查詢語句是與關係資料庫繫結在一起的,SQL查詢語句中的主體是資料庫表及表的欄位 HQL的查詢演示 1、HQL的查詢格式 支援 方法鏈的程式設計,即直接呼叫list()方法 程式碼: session.createQuery("from Customer").list(); 2、使用別名的方式 session.createQuery("from Customer c").list(); session.createQuery("select c from Customer c").list(); 3、排序查詢 排序查詢和SQL語句中的排序的語法是一樣的 升序 session.createQuery("from Customer order by cust_id").list(); 降序 session.createQuery("from Customer order by cust_id desc").list(); 4、分頁查詢 Hibernate框架提供了分頁的方法,可以呼叫方法來完成分頁 limit ?,? (當前頁-1)*pageSize setFirstResult(a) 從哪條記錄開始,如果查詢是從第一條開始,值是0 setMaxResults(b) 每頁查詢的記錄條數 List<LinkMan> list = session.createQuery("from LinkMan").setFirstResult(0).setMaxResults().list(); 5、帶條件的查詢 setParameter("?號的位置,預設從0開始","引數的值"),不用考慮引數的具體型別 按位置繫結引數的條件查詢(指定下標值,預設從0開始) 按名稱繫結引數的條件查詢(HQL語句中的問號換成 :名稱的方式) Query query = session.createQuery("from Linkman where lkm_name like ? order by lkm_id desc"); query.setFirstResult(0).setMaxResults(3); query.setParameter(0,"%run%"); List<Linkman> list = query.list(); for(Linkman linkman:list){ syso(linkman); } 投影查詢 1、投影查詢就是想查詢某一欄位的值或者某幾個欄位的值 如果查詢多個欄位 List<Object[]> list = session.createQuery("select c.cust_name,c.cust_level from Customer c").list(); for(Object[] objects:list){ syso(Arrays.toString(objects)); } 如果查詢兩個欄位,也可以把這兩個欄位封裝到物件中 現在持久化類中提供對應欄位的構造方法 使用 List<Customer> list = session.createQuery("select new Customer(c.cust_name,c.cust_level) from Customer c").list(); for(Customer customer:list) { System.out.println(customer); } 聚合函式查詢 1、獲取總的記錄數 Session session = HibernateUtils.getCurrentSession(); Transaction tr = session.beginTransaction(); List<Number> list= session.createQuery("select count(l) from Linkman l").list(); Long count = list.get(0).longValue(); System.out.println("數量:"+count); tr.commit(); 2、獲取某一列資料的和 Session session = HibernateUtils.getCurrentSession(); Transaction tr = session.beginTransaction(); List<Number> list= session.createQuery("select sum(lkm_id) from Linkman l").list(); Long count = list.get(0).longValue(); System.out.println("數量:"+count); tr.commit(); QBC檢索 0、QBC: query by criteria 按條件進行查詢 1、簡單查詢 使用的Criteria介面 Criteria criteria = session.createCriteria(Customer.class); List<Customer> list = criteria.list(); for(Customer customer:list){ System.out.println(customer); } 2、需要使用addOrder()方法來設定引數,引數使用org.hibernate.criterion.Order物件 Session session= HibernateUtils.getCurrentSession(); Transaction tr = session.beginTransaction(); //建立QBC介面 Criteria criteria = session.createCriteria(Linkman.class); //呼叫排序的方法,addOrder() criteria.addOrder(Order.desc("lkm_id")); List<Linkman> list = criteria.list(); for(Linkman linkman:list){ System.out.println(linkman); } tr.commit(); 3、分頁查詢 QBC的分頁查詢也是使用兩個方法 criteria.setFirstResult(0); criteria.setMaxResults(3); 4、條件查詢(Criterion是查詢條件的介面,Restrictions類是Hibernate框架提供的工具類,使用該類來設定查詢條件) 新增查詢使用Criteria介面的add方法,用來傳入條件 使用Restrictions的新增條件的方法來新增條件 Restrictions.eq 相等 Restrictions.st 大於號 Restrictions.ge 大於等於 Restrictions.lt 小於 Restrictions.le 小於等於 Restrictions.between 在之間 Restrictions.like 模糊查詢 Restrictions.in 範圍 Restrictions.and 並且 Restrictions.or 或者 Session session= HibernateUtils.getCurrentSession(); Transaction tr = session.beginTransaction(); //建立QBC介面 Criteria criteria = session.createCriteria(Linkman.class); //select * from cst_linkman where lkm_gender = 'man' or lkm_id >2L; criteria.add(Restrictions.or(Restrictions.eq("lkm_gender","man"),Restrictions.gt("lkm_id",3L))); List<Linkman> list = criteria.list(); for(Linkman linkman:list){ System.out.println(linkman); } tr.commit(); 5、聚合函式查詢(Projection是聚合函式的介面,而Projections是Hibernate提供的工具類) 需要使用criteria.setProjection Demo3#run9 離線條件查詢 1、離線條件查詢使用的是DetachedCriteria介面進行查詢,離線條件查詢物件在建立的時候,不需要使用Session物件,只是在查詢的時候使用Session物件即可 Demo3#run10 SQL查詢方式 Demo4#run1,run2 多表查詢 1、多表的查詢用HQL語句進行查詢 HQL語句和SQL語句的語法比較相似 內連線查詢 顯示內連線 select * from customers c inner join orders o on c.cid = o.cno; 隱式內連線 select * from customers c ,orders o where c.cid = o.cno 外連線 左外連線 select * from customers c left outer join orders o on c.cid=o.cno 右外連線 select * from customer c right outer join orders o on c.cid=o.cno 2、HQL的多表查詢 迫切和非迫切 非迫切返回結果是Object[] Demo5#run1 迫切連線返回的結果是物件,把客戶的資訊封裝到客戶的物件中,把訂單的資訊封裝到客戶的Set集合中 Demo5#run2 3、內連線查詢 內連線使用 inner join,預設返回的是Object陣列 迫切內連線 inner join fetch 返回的是實體物件 4、左外連線查詢 左外連線:封裝成List<Object[]> 迫切左外連線 Session session = HibernateUtils.getCurrentSession(); Transaction tr = session.beginTransaction(); List<Customer> list = session.createQuery("from Customer c left join fetch c.linkmans").list(); Set<Customer> set = new HashSet<Customer>(list); for(Customer customer:list){ syso(customer); } tr.commit(); 延遲載入 屬性沒有好壞之分 只有適不適合 1、延遲載入先獲取到代理物件,當真正使用到該物件中的屬性的時候,才會傳送SQL語句,Hibernate框架提升效能的方式 2、類級別的延遲載入 Session物件的load方法預設就是延遲載入 Customer c = session.load(Customer.class,1L);沒有傳送SQL語句,當使用該物件的屬性時,才傳送SQL語句 標籤的優先順序高 使類級別的延遲載入失效 在<class>標籤上配置 lazy="false" xxx.hbm.xml Hibernate initialize(Object proxy) Demo6#run2 3、關聯級別的延遲載入(查詢某個客戶,當檢視該客戶下的所有聯絡人是否是延遲載入) 預設是延遲載入 Demo6#run3 查詢策略 1、使用Hibernate查詢一個物件的時候,查詢其關聯物件,應該如何查詢,是Hibernate的一種優化手段 2、Hibernate框架的檢索策略解決的問題 查詢的時機 Customer c1 = session.get(Customer.class,1L); syso(c1.getLinkmans().size()); lazy屬性解決查詢的時機的問題,需要配置是否採用延遲載入 查詢的語句形式 List<Customer> list = session.createQuery("from Customer").list(); for(Customer c:list){ syso(c.getLinkmans()) } fetch屬性可以解決查詢語句的形式的問題 set標籤上配置策略 1、使用fetch和lazy fetch的取值 控制SQL語句生成的格式 select 預設值,傳送查詢語句 join 連線查詢,傳送的是一條迫切左外連線,配置了join.lazy就失效了 subselect 子查詢,傳送一條子查詢查詢其關聯物件(需要使用list()方法進行測試) lazy的取值 查詢關聯物件的時候是否採用延遲 true 預設 延遲 false 不延遲 extra 極其延遲 2、set標籤上的預設值是fetch="select" lazy="true" 3、hibernate框架都採用了預設值,開發中基本都是預設值 many-to-one 標籤上配置策略 1、<many-to-one>標籤上使用fetch和lazy屬性 fetch的取值 控制sql的格式 select 預設,傳送基本select語句查詢 join 傳送迫切左外連線查詢 lazy任何值一樣的效果 lazy的查詢 控制載入關聯物件是否採用延遲 false 不採用延遲載入 proxy 預設值,代理,現在是否採用延遲 由另一端上的<class>的lazy確定,如果這端的class上的lazy="true" proxy的值就是true(延遲載入) 如果class上lazy="false" proxy的值就是false 屬性沒有好壞之分 只有適不適合