9.27 Hibernate 完全大複習(全部)

   今天呢,我開始鞏固下hibernate,當然還是跟着老師的講課班,不過第二次聽,那感覺就是不一樣。早在過去懞懞懂懂,或者根本不知道的知識,全部回顧瞭解了一遍。     正所謂:書讀百變,其義自見~!  太爽了,好開心~!  既然學,那就認真點。 此貼陸續把每次鞏固的收穫寫上來的。

 

hibernate建立數據的的映射是完全可以通過eclips自動導入實現的,不過,基礎還是要學的。知其解決方法,也要知其理纔行~!

(~ o ~)~zZ  以下是收穫:

---------------------------------------------------------------------------------------------

xml形式的實體化映射:

 

*.hbm.xml
<hibernate-mapping>
<class name="實體化類名" table="表名">
   <id> 定義一個單主鍵,一個字段  屬性作爲實體類的主鍵
   <composite-id> 複合主鍵,多個字段  一組屬性作爲主鍵的定義方式 (主鍵類,實現序列化接口)
   <property> 字段---》屬性的映射
  </class>

</hibernate-mapping>

 

練習:
emp-->dept   多對一  實現級聯,添加,刪除操作

 

首先寫好emp和dept實體化類   emp爲主表實體化類,所以emp有dept類的對象作爲屬性

接着寫映射文件.hbm.xml

emp.hbm.xml如下:

dept.hbm.xml 如下:

 

 注意了:
在寫pojo類時,*.hbm.xml寫完之後,
還要將hibernate.cfg.xml之後加入
<mapping resource="cn/com/vo/Emp.hbm.xml" />
<mapping resource="cn/com/vo/Dept.hbm.xml" />類似這樣的地址,實現pojo類在hibernate中的關係映射


(自動通過數據庫導入的pojo類,eclips會自動將其地址加在hibernate.cfg.xml中

hbm2ddl.auto  這個在hibernate.cfg.xml中若是設置爲true,則會根據映射關係在數據庫中建立相應的table,假如數據有了~就不會建了。

 

cascade 有以下取值:

 

all : 所有操作都傳遞到相關聯的對象
save-update 保存和更新傳遞到相關聯的對象
delete 刪除操作傳遞到相關聯的對象
delete-orphan : 所有操作都傳遞到相關聯的對象 並刪除不再與父對象關聯的對象。

-----------------------------------------------------------------------------------------------------------------------------------------

級聯刪除這要找到數據庫裏的對象
用Emp emp=(Emp)session.get(Emp.class,7935");
  session.delete(emp);
這樣會把emp表和相關聯的dept表中的數據都刪掉

-----------------------------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------------------------

 

從表---主表, 一對多的關係 (Onetomany)
hibernate 之中的集合有 list,map,set,bag 在一對多中經常用的時set--原理:去空值,去重複 (難怪呢)
類之間用set實現1 對n
配置上,
<one-to-many>

<set 的屬性有 :>
name 屬性名 
table 基於關聯表的一對多關係
lazy="true/false"是否使用延遲加載技術——不錯!true,沒有用到關聯表,則不會把關聯表的信息搜出來,加載到緩存中,反之則會嚴重影響其性能~ 平時就要檢查設置爲true hibernate 3.0以後基本默認都是true
inverse(true/false) 關聯關係由哪一方來維護 true--會根據從表實體類維護 false--會根據主表實體類維護
out-join
fetch
orderby 對關聯表排序
---
 <key column="設置從表的外鍵字段'></key>
   <one-to-many class="從表實體類"/>

dept和emp是 1對多的關係

1 將dept實體類中加入emps 的set集,然後get/set方法

只需要將dept.hbm.xml改下即可:

 

 

 ----------------------------------------------------------------------------------------------------------------------------------------------

<many-to-many> 多對多
例子:學生表 關聯表 老師表
<set >的屬性
name
table 中間表
<key column="中間表的與當前表所映射的外鍵字段">
<many-to-many culumn="中間表與關係的另一個表所建立的關聯字段">

這裏給出一個寫在一起的many-to-many.hbm.xml

 

9.28 Hibernate 特殊表的關聯 和  繼承在hibernate 實現持久化的作用

1對1(外主)
1對多(中間表的)
繼承,通過繼承實現hibernate數據化的持久性操作

1對1關係
 第一種情況:a表引用b表的主鍵做外鍵具有唯一性約束
一個人對應一個地址
 person    address
-------------------
 p_id        a_id
 p_name      a_name
 a_id 外鍵+了唯一性約束
<many-to-one>
將many改成unique="true"
這個還是比較容易理解的。

 

 

第二中情況:a表引用b表的主鍵,在a表中既做主鍵,也做外鍵
person  address
----------------
p_id     a_id( 它是引用p_id的外鍵)
p_name   a_name
<one-to-one name="person" constrained="true"></one-to-one>只對主鍵進行描述

<one-to-one name="關聯屬性"> 在hibernate機制上描述兩個實體1對1的關係
在操作時基於兩個標的主鍵進行關聯操作

基於該關係生成外鍵約束,或在某一鍵上加上某一屬性
將contraonted="true"基於關係生成外鍵約束

column 描述關聯字段(外鍵1對1關係,需要從主表這邊描述的時候)

在它的<id 屬性上>
  <genertor ,,
</id>

 

繼承 在 hibernate中的作用
單表繼承
在一個表中,通過一個標識來區分不同的數據類型,如type字段
用戶有:學生,老師的例子不錯啊
type屬性 

<id...>
<discrimininator column="type類型的字段名 user_type">
</discrimininator>
<property...>
<subclass name="子類的名稱" discriminator-value="標識字段爲何值用該子類">
  <property name="teacherPhoto" column="teacher_photo"></property>
</subclass>

 繼承在hibernate中的強勢應用。這是單表的繼承。
(類之間要有繼承user被student 和teacher繼承,配置如上)

 

關聯表的繼承。
用戶表是雙方都有的信息
學生,老師是自己獨有的基礎信息表
         用戶
           |
           |
----------------------------
學生                    老師

配置中用<joined-subclass>---繼承關聯
<joined-subclass name="類名" table="表名">
<key clumn="關聯外鍵字段"/>
<property name="" clumn=""/>
<many-to-one>..</...>
</joined-subclass>

 

 

 在上面的特殊表關聯中,要體會其原理,還有對 unique="true"的理解。。這個理解真的挺重要的。

-------------------------------------------------
會用hibernate做項目和你懂hibernate完全是兩個概念。。  是的,知道原理,寫起代碼不再是機械式的填充。

 --------------------------------------------------------------------------------------------------------------------------------

hibernate 持久化對象的生命週期
session作爲持久化對象 有3個狀態:
1 瞬時狀態--由new關鍵字創建生成的對象狀態,這種對象只會在內存中存在
            狀態沒有和數據庫同步
            session中沒有持久該對象的引用。(數據對象有可能丟失)
2 持久狀態--對象是由session創建生成(如session.save()   session.update())
            session持有該對象引用後,將其狀態也入到數據庫中
3 離線狀態--原本爲持久狀態的對象,因session.close() 即 session資源的關閉或者session清空實體對象的            引用,導致該對象不再由session管理,稱作離線狀態

new(新生)----get/load()--》持久狀態 session.load是按主鍵檢索數據,創建持有對象,以及持久對象的代理對象,返回的是代理對象。
  |
  |
  |
瞬時狀態   ----save(),saveOrUpdate() ----》持久狀態 ---evict()清除指定類型id clear()清除所有 close()-----》離線狀態

離線對象---update(),saveOrUpdate(),lock()-->持久對象-----delete()--》瞬時狀態

hibernate每一個類都要配置一個id,表示唯一性。那麼session的表示id也只有一個,因爲唯一性的存在,反之,數據的維護變的相當混亂
---------------------------------------------------------------------------------
Hibernate 檢索語言 Hql
"from 類名 where 屬性名=? ";將查詢的結果封裝成類名所對應的類實例對象

hql的關聯查詢:
select a.dept.deptno from Emp a 會根據實體類之間的關聯,自動生成多表關聯的sql
from Emp a where a.dept.dname=?     hql果然強大~!

Query query=session.createQuery("from Emp a where a.dept.dname=?");
query.setString(0,"教育部");
List<Emp> result=query.list();

在hql中一旦出現select子句,它肯能查詢出的結果不按照from的類名封裝對象,而是將結果放在Object[]中

Query query=session.createQuery("select a.dept.dname.a.sal from Emp a where a.dept.dname=?");
query.setString(0,"教育部");
List<Object[]> result=query.list();

如果這樣你用着還不是很爽,可以利用hibernate實現有參的構造函數
Query query=session.createQuery("select new Emp(a.dept.dname.a.sal) from Emp a where a.dept.dname=?");//前提Emp有這樣一個構造函數。
query.setString(0,"教育部");
List<Emp> result=query.list();

------------------------hibernate的強大在於你可以根據自己的需求設計出合理的方式完成檢索操作~贊一個!

hql函數的使用:
聚合函數:avg()  sum() max() count()
查詢關鍵字:distinct
集合操作函數:size(),minelement(),minindex(),maxindex()
Orderby  子句   group by 子句

例子:"from Dept a where size(a.emps)>=2";
---------------------------------------------------
連接查詢
inner join  基於關聯屬性經行操作       inner join fetch

Query query=session.createQuery("from Dept dept inner join fetch dept.emps");
query.list();

Left outer join                     left outer join fecth
Right outer hoin 
Fetch只對inner join 和Left join 有效,Right outer join返回的是數組

-----------------------------
Query query=session.getNamedQuery("leftjoin");//這個是在xml的配置文件中寫的cdata..這個問題解決就好了
query.list();

 

---------------------------------------------------------------------------------------------------------------

補充的知識:
標準查詢
SQL查詢
附:攔截器
    驗證器
    鎖策略--樂觀鎖,悲觀鎖的操作實現


標準查詢---面向對象技術//這個沒有sql,或者hql語句靈活,也沒他們可讀性強。這種語言只能作爲輔助
 sql---------->對象的方法
Criteria cr=session.createCriteria(Emp.class);
cr.add(Expression.gt("sal",1000));//Expression是一個接口關於Criteria
List result=cr.list();
Emp emp=null;
for(int i=0;i<result.size();i++){
  emp=(Emp)result.get(i);
}


標準查詢是基於Critera.add(查詢條件)    查詢條件由Experssion生成對象,根據不同的條件方法調度,生成對應的查詢條件  Experssion方法有很多(eq,gt,like等)

-------------------
SQl 查詢
sql語句的通用性很差。不同的版本oracle會使用到不同的sql語句語法。容易出錯。 瞭解下了
而HQL則無需考慮這些。
SQLQuery sqlQuery=session.createSQLQuery("select ename,job,sal from emp where deptno=?");
Query query=session.getNamedQuery("leftjoin");//這個是在xml的配置文件中寫的cdata..
sqlQuery.setInteger(0,10);
List list=sqlQuery.list();

-----------------------

攔截器--設置在sessionFactory之上,對session的持久化操作就行攔截
EmptyInterceptor  是個抽象類,我們的類需要實現它。
加入方法用eclipse的 overwrite中找到對應的方法即可!!!
onDelete()
onLoad()
onSave()
這是繼承EmptyInterceptor 的類例如MyInterceptor
那麼在實現類中 加入
Configuration  configuration = new Configuration().configure();
configuration.setInterceptor(new MyInterceptor())//這個是加入的。。!!!
SessionFactory sessionFactory = configuration.buildSessionFactory();
------------------------------------
驗證器
驗證接口--用於在數據的添加,修改時,在持久化操作之前,對數據有效性驗證。
validator---validate() throws ValidationFailure
validate()可以終止原有的持久化操作。

-----------------------------------
鎖策略 
鎖機制 ---在併發訪問下,保護資源有序的被使用
樂觀鎖  悲觀鎖
Hibernate 鎖策略

Hibernate 內部鎖機制

LockMode.NONE 無鎖機制

LockMode.WRITE  hibernate 進行保存和更新時自動使用的鎖機制。

LockMode.READ hibernate 讀取紀錄時的機制

悲觀鎖

整個數據處理過程中,將數據處於鎖定
狀態。悲觀鎖的實現,往往依靠數據庫提供的鎖機制

LockMode.UPGRADE

LockMode.UPGRADE_NOWAIT

 //相當於SQL(for update  中的 wait 或者nowaite)

實現機制如下:

Criteria.setLockMode

Query.setLockMode(Strng指hql語句中實體類的別名,LockMode.UPGRADE);
例如:
Query query=session.createQuery("from Emp a");
Query.setLockMode(a,LockMode.UPGRADE_NOWAIT);

Emp emp=(Emp)session.load(Emp.class,1,LockMode.UPGRADE_NOWAIT);//悲觀鎖

session.lock (實例對象,LockMode.READ);
缺點:資源開銷大,一般不用這種,通常推薦使用樂觀鎖機制

樂觀鎖

更加寬鬆的加鎖機制,悲觀鎖對長事務而言,開銷往往無法承受;避免死鎖。

實現機制:
Hibernate在o/R中映射特殊字段<timestamp>  或者<version>
採用特殊字段來做判斷,平時操作不等待,但是保存或者更新時會進行判斷。


Version

Dirty

ALL

主要介紹 Version

官方推薦的樂觀鎖實現策略,廣泛使用,具有經驗可借鑑性

實現舉例:在每一次進行讀取操作時取出版本號,在進行更新時同時刷新版本號,更新時只能更新低版本的數據,從而完成鎖策略。 Hibernate 的 Session 會在等待用戶交互時 ,Session 斷開數據庫連接。在整個應用事務過程中, Hibernate 使用單例 Session 和單例類來實現。

使用方法:

<class name="UserVo" table="uservo" schema="SPRINGDEV" optimistic-lock="version">

< 主鍵 >

<version name="version"  column="version"   type="java.lang.Integer"  /> 

同時數據庫表中增加字段  version ,version無須設置,它會隨着操作自動增加。

總結:在一般性的事務中,大可將鎖機制拋開不用,這樣不可否認增加了複雜性,你不得不面對不少的版本異常信息,只有在涉及關鍵業務如進行網上購物的付款等就必須進行加鎖管理,當然推薦基於 version 的樂觀鎖管理。

 

-------------------------------------------------------------------------------------------------------------

hibernate 空值異常
     
     字段 ---》屬性(基本數據類型)(包裝類型,字符,日期)
  基本數據類型(int,double,char等)
        優:性能好
      缺點:不能接受空字段的值
  包裝類:如Double,String,Date,Integer(就是java.lang.*這種包裝類)
        優:能包裝空值在內的所有有效數值
      缺點:資源開銷大

提示:如果數據封裝不上pojo類,有可能就是數據類型選擇的錯誤!
----------------------------------------------------------------------------
這樣的錯誤:
<c:forEach var="dt" items="${requestScope.list}">
   <tr>
  <td>${dt.empno}</td>
  <td>${dt.ename}</td>
  <td>${dt.job}</td>
  <td>${dt.sal}</td>
  <td>${dt.dept.deptno}</td>//可以顯示的,它在emp表中作爲外鍵<many-to-one name="dept".. ><column

name="DEPTNO"/></many-to-one>
  <td>${dt.dept.dname}</td>//這個不可以顯示,它跟emp無任何關聯。是dept獨有的。會報session已經關閉。以下

有解決辦法。
  </tr>
</c:forEach>

session是線程不安全,不能被多個線程同時使用
web-線程->請求處理  一個請求可以對應一個session線程。

利用java.lang.ThreadLocal  會爲每一個當前線程分配一個獨立的存儲空間
Map<key,value>會爲這一個線程保存獨有的線程信息
以下爲代碼:
--------------------------------------------------------
view plaincopy to clipboardprint?
package cn.com.csuinfosoft.hibernate;  
 
import org.hibernate.Session;  
import org.hibernate.SessionFactory;  
import org.hibernate.cfg.Configuration;  
 
public class HibernateUtil {  
 
 private static SessionFactory sessionFactory = null;  
   
 private static ThreadLocal threadLocal = new ThreadLocal();  
   
 static {  
  try {  
   Configuration config = new Configuration().configure();  
   sessionFactory = config.buildSessionFactory();  
  } catch (Exception ex) {  
   ex.printStackTrace();  
  }  
 }  
   
 public static Session getSession() {  
  Session session = (Session)threadLocal.get();//獲取當前線程對應的內存空間中,存儲的對象  
  if(session == null) {  
   session = sessionFactory.openSession();  
   threadLocal.set(session);  
  }  
  return session;  
 }  
   
 public static void closeSession() {  
  Session session = (Session)threadLocal.get();  
  if(session != null) session.close();  
  threadLocal.set(null);  
 }  
   

package cn.com.csuinfosoft.hibernate;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

 private static SessionFactory sessionFactory = null;
 
 private static ThreadLocal threadLocal = new ThreadLocal();
 
 static {
  try {
   Configuration config = new Configuration().configure();
   sessionFactory = config.buildSessionFactory();
  } catch (Exception ex) {
   ex.printStackTrace();
  }
 }
 
 public static Session getSession() {
  Session session = (Session)threadLocal.get();//獲取當前線程對應的內存空間中,存儲的對象
  if(session == null) {
   session = sessionFactory.openSession();
   threadLocal.set(session);
  }
  return session;
 }
 
 public static void closeSession() {
  Session session = (Session)threadLocal.get();
  if(session != null) session.close();
  threadLocal.set(null);
 }
 
}
 
//在實現類中通過 Session session=HibernateUtil.getSession()這樣得到的session是在同一個請求中保持不變的


然後當我們需要在請求結束關閉這樣個一session可以寫filter文件:
-------------------------
view plaincopy to clipboardprint?
package cn.com.csuinfosoft.filter;  
 
import java.io.IOException;  
 
import javax.servlet.Filter;  
import javax.servlet.FilterChain;  
import javax.servlet.FilterConfig;  
import javax.servlet.ServletException;  
import javax.servlet.ServletRequest;  
import javax.servlet.ServletResponse;  
 
import cn.com.csuinfosoft.hibernate.HibernateUtil;  
 
public class HibernateFilter implements Filter {  
 
 public void destroy() {  
 
 }  
 
 public void doFilter(ServletRequest request, ServletResponse response,  
   FilterChain filterChain) throws IOException, ServletException {  
  try {  
   System.out.println("============ Filter try ====== Thread:" +   
 
Thread.currentThread().getName());  
   filterChain.doFilter(request, response);  
  } finally {  
   System.out.println("============ Filter finally ======Thread:" +   
 
Thread.currentThread().getName());  
   HibernateUtil.closeSession(); //每次請求結束前關閉Session  
  }  
    
 }  
 
 public void init(FilterConfig filterConfig) throws ServletException {  
    
 }  
 

package cn.com.csuinfosoft.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import cn.com.csuinfosoft.hibernate.HibernateUtil;

public class HibernateFilter implements Filter {

 public void destroy() {

 }

 public void doFilter(ServletRequest request, ServletResponse response,
   FilterChain filterChain) throws IOException, ServletException {
  try {
   System.out.println("============ Filter try ====== Thread:" +

Thread.currentThread().getName());
   filterChain.doFilter(request, response);
  } finally {
   System.out.println("============ Filter finally ======Thread:" +

Thread.currentThread().getName());
   HibernateUtil.closeSession(); //每次請求結束前關閉Session
  }
 
 }

 public void init(FilterConfig filterConfig) throws ServletException {
 
 }

}

 

最後將這樣一個filter配置在web.xml中,是相當容易的。
----------------------------

 
補充:SessionFactory可以在監聽器控制下, 是要在程序卸載的時候關閉掉。

在過去所學的線程中Thread 中獲得當前線程方法爲currentThread()

 hibernate的配置優化
<property name="jdbc.batch_size">30</property>   這個用於管理數據庫批量處理的,如批量刪除
<property name="jdbc.fetch_size">50</property> 在jdbc抓取數據時採用分批抓取,一次可以抓取50條

做一個簡單 批量刪除 實現,不是很難哦!

 

----------------------------------------------------------------------------------------------------------------

不懂得問題:

<class name="UserVo" table="uservo" schema="SPRINGDEV" optimistic-lock="version">

< 主鍵 >

<version name="version"  column="version"   type="java.lang.Integer"  /> 

</class>

 

解釋下schema="SPRINGDEV" 和optimistic-lock="version":

1)其中<class name="UserVo" table="uservo" schema="SPRINGDEV" optimistic-lock="version">中的schema="SPRINGDEV"表示數據庫的用戶名。如果當前鏈接數據庫的用戶名稱不是SPRINGDEV的話,實際操作中還是會用SPRINGDEV這個用戶來操作。這就會產生一系列問題。

 

2)optimistic-lock屬性有如下可選取值:
? none 無樂觀鎖
? version 通過版本機制實現樂觀鎖
? dirty 通過檢查發生變動過的

 

-------------------------------------------------------------------------------------------------------------------------

 

Hibernate 關閉sessionFactory :

  關閉sessionFactory是應在服務器被關閉,程序被卸載時關閉,所以需要寫一個sessionFactory特有的監聽類,當服務器被關閉時,自動關閉sessionFactory.
寫個監聽類 實現ServletContextListener 在該類中關閉關閉sessionFactory ,以下就是:

 


將監聽類配置在web.xml 中


 <listener>
  <listener-class>cn.com.csuinfosoft.listener.HibernateListener</listener-class>
 </listener>

 

 -------------------------------------------------------------------------------------

 

---------------------------------------------------------------以下轉載的,一些關鍵字的注意,配合着學習:

重點學習 Hibernate fetch lazy cascade inverse 關鍵字

 

Hibernate最讓人頭大的就是對集合的加載形式。
書看了N次了,還是沒有真正理解Hibernate。所以下午專門做了下測試,對配置文件的意思加深了認識。

假設有兩個表,Photos(一) --- picture(多)Photo包含picture集合

結論1: HQL代碼 > fetch(配置) > lazy (配置)
結論2: 默認 lazy="true"
結論3: fetch 和 lazy 主要是用來級聯查詢的,   而 cascade 和 inverse 主要是用來級聯插入和修改的

             fetch參數指定了關聯對象抓取的方式是select查詢還是join查詢,select方式時先查詢返回要查詢的主體對象(列表),再根據關聯外鍵id,每一個對象發一個select查詢,獲取關聯的對象,形成n+1次查 詢; 而join方式,主體對象和關聯對象用一句外鍵關聯的sql同時查詢出來,不會形成多次查詢。
如果你的關聯對象是延遲加載的,它當然不會去查詢關聯對象。 另外,在hql查詢中配置文件中設置的join方式是不起作用的(而在所有其他查詢方式如get、criteria或再關聯獲取等等都是有效的),會使用select方式,除非你在hql中指定join fetch某個關聯對象。fetch策略用於定義 get/load一個對象時,如何獲取非lazy的對象/集合。 這些參數在Query中無效。

在某種特殊的場合下,fetch在hql中還是起作用的。
例如
現有message(回帖)-->topic(主貼)-->forum(版塊) 的多級many-to-one結構:
第一級:message-->topic many-to-one配置lazy="false" fetch="join"
第二級:topic-->forum many-to-one配置lazy="false" fetch="join"
這時如果"from message",則第二級:topic-->forum中的fetch策略會起作用

查詢抓取(默認的)在N+1查詢的情況下是極其脆弱的,因此我們可能會要求在映射文檔中定義使用連接抓取:

<set name="permissions"
fetch="join">
<key column="userId"/>
<one-to-many class="Permission"/>
</set
<many-to-one name="mother" class="Cat" fetch="join"/>
在映射文檔中定義的抓取策略將會有產生以下影響:

通過get()或load()方法取得數據。

只有在關聯之間進行導航時,纔會隱式的取得數據(延遲抓取)。

條件查詢

在映射文檔中顯式的聲明 連接抓取做爲抓取策略並不會影響到隨後的HQL查詢。

通常情況下,我們並不使用映射文檔進行抓取策略的定製。更多的是,保持其默認值,然後在特定的事務中, 使用HQL的左連接抓取(left join fetch) 對其進行重載。這將通知 Hibernate在第一次查詢中使用外部關聯(outer join),直接得到其關聯數據。 在條件查詢 API中,應該調用 setFetchMode(FetchMode.JOIN)語句。


其實這並不能說明hql能夠按照配置文件設置的join進行抓取,這時 第二級:topic-->forum 的抓取其實已經和hql沒有關係了,因爲前面已經產生了另一個select方式的抓取語句。
而是對象的關聯獲取,假如查詢message時topic是設置爲延遲加載的,那麼在後面獲取message.topic時,如topic.forum不延遲加載,那麼topic-->forum會實現配置的join方式的抓取,這個顯然和hql查詢沒有關係。

結論4: 如果你是用spring來幫你管理你的session, 並且是自動提交,延遲加載就等於沒加載~_~(當然
                除非你手動重新打開session然後手動Hibernate.initialize(set);然後關閉session.
結論5:      cascade主要是簡化了在代碼中的級聯更新和刪除。
j結論6:老爸可以有多個孩子,一個孩子不能有多個老爸,而且老爸說的算, 孩子圍着老爸轉。
                所以Photos老爸要有權力所以 cascade 這個關鍵子都是送給老爸的, 也就是級聯更新,
               老爸改姓了,兒子也得跟着改,呵呵。“不然,就沒有零花錢咯”。
                而Picture兒子整體捱罵,但是還是要維護父子之間良好的關係,對老爸百依百順,所
               以老爸就說,兒子,“關係,由你來維護(inverse="true") ,不然就不給零花錢。呵。”。
               <set name="pictures" inverse="true" cascade="all">
                    <key>
                       <column name="photosid" not-null="true" />
                    </key>
                 <one-to-many class="girl.domain.Picture" />
             </set>
               
測試代碼:

    Photos p = ps.getById(1);
   Set<Picture> set = p.getPictures();
   for(Picture pic : set){
    System.out.println(pic.getId());
   }

配置文件的一部分:
       <set name="pictures" inverse="true" cascade="all" >
            <key>
                <column name="photosid" not-null="true" />
            </key>
            <one-to-many class="girl.domain.Picture" />
        </set>

測試過程會對配置文件不斷修改:並且從來不曾手動重新打開session

測試結構:

當配置條件爲 lazy=true 一句查詢 測試代碼中沒有調用getPicture() 正常
Hibernate: select photos0_.id as id0_0_, photos0_.userid as userid0_0_, photos0_.typeid as typeid0_0_, photos0_.name as name0_0_, photos0_.createtime as createtime0_0_, photos0_.description as descript6_0_0_, photos0_.faceid as faceid0_0_, photos0_.uri as uri0_0_ from super.photos photos0_ where photos0_.id=?

lazy=true 一句查詢 有getPicture()
Hibernate: select photos0_.id as id0_0_, photos0_.userid as userid0_0_, photos0_.typeid as typeid0_0_, photos0_.name as name0_0_, photos0_.createtime as createtime0_0_, photos0_.description as descript6_0_0_, photos0_.faceid as faceid0_0_, photos0_.uri as uri0_0_ from super.photos photos0_ where photos0_.id=?


lazy=true 一句查詢 有getPicture() 並且訪問了裏面的元數Picture 且有異常拋出
Hibernate: select photos0_.id as id0_0_, photos0_.userid as userid0_0_, photos0_.typeid as typeid0_0_, photos0_.name as name0_0_, photos0_.createtime as createtime0_0_, photos0_.description as descript6_0_0_, photos0_.faceid as faceid0_0_, photos0_.uri as uri0_0_ from super.photos photos0_ where photos0_.id=?


lazy="false" 兩句查詢 肯定沒問題,因爲全部數據都個查了出來 所以怎麼調用都正常
Hibernate: select photos0_.id as id0_0_, photos0_.userid as userid0_0_, photos0_.typeid as typeid0_0_, photos0_.name as name0_0_, photos0_.createtime as createtime0_0_, photos0_.description as descript6_0_0_, photos0_.faceid as faceid0_0_, photos0_.uri as uri0_0_ from super.photos photos0_ where photos0_.id=?
Hibernate: select pictures0_.photosid as photosid1_, pictures0_.id as id1_, pictures0_.id as id2_0_, pictures0_.photosid as photosid2_0_, pictures0_.name as name2_0_, pictures0_.clicked as clicked2_0_, pictures0_.uploaddate as uploaddate2_0_, pictures0_.size as size2_0_, pictures0_.description as descript7_2_0_, pictures0_.uri as uri2_0_ from super.picture pictures0_ where pictures0_.photosid=?


fetch="join" 一句查詢 效果 == lazy="false" 呵呵,哪個效率高,我就不知道了。。。。。。。。。。。
Hibernate: select photos0_.id as id0_1_, photos0_.userid as userid0_1_, photos0_.typeid as typeid0_1_, photos0_.name as name0_1_, photos0_.createtime as createtime0_1_, photos0_.description as descript6_0_1_, photos0_.faceid as faceid0_1_, photos0_.uri as uri0_1_, pictures1_.photosid as photosid3_, pictures1_.id as id3_, pictures1_.id as id2_0_, pictures1_.photosid as photosid2_0_, pictures1_.name as name2_0_, pictures1_.clicked as clicked2_0_, pictures1_.uploaddate as uploaddate2_0_, pictures1_.size as size2_0_, pictures1_.description as descript7_2_0_, pictures1_.uri as uri2_0_ from super.photos photos0_ left outer join super.picture pictures1_ on photos0_.id=pictures1_.photosid where photos0_.id=?

不加fetch="join" 一句查詢 沒有getPicture() 正常
Hibernate: select photos0_.id as id0_0_, photos0_.userid as userid0_0_, photos0_.typeid as typeid0_0_, photos0_.name as name0_0_, photos0_.createtime as createtime0_0_, photos0_.description as descript6_0_0_, photos0_.faceid as faceid0_0_, photos0_.uri as uri0_0_ from super.photos photos0_ where photos0_.id=?

不加fetch="join" 一句查詢 有getPicture() 正常
Hibernate: select photos0_.id as id0_0_, photos0_.userid as userid0_0_, photos0_.typeid as typeid0_0_, photos0_.name as name0_0_, photos0_.createtime as createtime0_0_, photos0_.description as descript6_0_0_, photos0_.faceid as faceid0_0_, photos0_.uri as uri0_0_ from super.photos photos0_ where photos0_.id=?

不加fetch="join" 一句查詢 有getPicture() 並且訪問裏面的元素Picture的ID 有異常拋出
Hibernate: select photos0_.id as id0_0_, photos0_.userid as userid0_0_, photos0_.typeid as typeid0_0_, photos0_.name as name0_0_, photos0_.createtime as createtime0_0_, photos0_.description as descript6_0_0_, photos0_.faceid as faceid0_0_, photos0_.uri as uri0_0_ from super.photos photos0_ where photos0_.id=?

來個兩兵交戰 fetch="join" lazy="true" 呵呵 結果,一句查詢, 結構正常 所以就當lazy不存在好了。 看來fetch 是老大。、、、、、、、、、、、、、
Hibernate: select photos0_.id as id0_1_, photos0_.userid as userid0_1_, photos0_.typeid as typeid0_1_, photos0_.name as name0_1_, photos0_.createtime as createtime0_1_, photos0_.description as descript6_0_1_, photos0_.faceid as faceid0_1_, photos0_.uri as uri0_1_, pictures1_.photosid as photosid3_, pictures1_.id as id3_, pictures1_.id as id2_0_, pictures1_.photosid as photosid2_0_, pictures1_.name as name2_0_, pictures1_.clicked as clicked2_0_, pictures1_.uploaddate as uploaddate2_0_, pictures1_.size as size2_0_, pictures1_.description as descript7_2_0_, pictures1_.uri as uri2_0_ from super.photos photos0_ left outer join super.picture pictures1_ on photos0_.id=pictures1_.photosid where photos0_.id=?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章