1. 程式人生 > >Hibernate開發要點

Hibernate開發要點

1.兩種配置檔案:
  A.hibernate.cfg.xml   和   B.hibernate.properties

  A中可含對映檔案的配置,而B中hard codes加對映檔案。

  A。Configuration config=new Configuration().config();
  B. Configuration config=new Configuration();
     config.addClass(TUser.class);


2.你不必一定用hibernate.cfg.xml或hibernate.properties這兩檔名,
   你也不一定非得把配置檔案放在Classes下,
   File file=new File("c://sample//myhibernate.xml");
   Configuration config=new Configuration().config(file);

3. session.Flush()
   強制資料庫立即同步,當用事務時,不必用flush,事務提交自動呼叫flush
   在session關閉時也會呼叫flush


4. Hibernate總是使用物件型別作為欄位型別

5. XDoclet專門建立了hibernate doclet,就是在java程式碼上加上一些
   java docTag,後來再讓XDoclet分析該java程式碼,生成對映檔案;

6.HQL子句本身大小寫無關,但是其中出現的類名和屬性名必須注意大小寫區分。

7.關係:
  Constrained : 約束,表明主控表的主鍵上是否存在一個外來鍵(foreigh key)
   對其進行約束。

  property-ref:關聯類中用於與主控類相關聯的屬性名,預設為關聯類的主鍵屬性名

  單向一對多需在一方配置,雙向一對多需在雙方進行配置

8.lazy=false:被動方的記錄由hibernate負責記取,之後存放在主控方指定的
  Collection型別屬性中

9. java.util.Set或net.sof.hibernate.collecton.Bag型別的Collection


10.重要:inverse:用於標識雙向關聯中的被動方一端。
         inverse=false的一方(主控方)負責維護關聯關係.預設值:false

11.batch-size:採用延遲載入特徵時,一次讀入的資料數昨。

12.一對多通過主控方更新(主控方為一方時)

   user.getAddresses().add(addr);
   session.save(user);//通過主控物件級聯更新  

13.在one-to-many 關係中,將many 一方設為主動方(inverse=false)將有助效能
   的改善。在一方設定關係時,inverse=true,即將主控權交給多方,
   這樣多方可主動從一方獲得foreign key,然後一次insert即可完工。


   addr.setUser(user);//設定關聯的TUser物件
   user.getAddresses().add(addr);
   session.save(user);//級聯更新 

14.只有設為主控方的一方才關心(訪問)對方的屬性,被動方是不關心對方的屬性的。

15.one-to-many與many-to-one節點的配置屬性不同:
   一對多關係多了lazy和inverse兩個屬性
   多對多節點屬性:column:中間對映表中,關聯目標表的關聯欄位
                   class:類名,關聯目標類
                   outer-join:是否使用外聯接    

   注意:access是設定屬性值的讀取方式。


        column是設定關聯欄位。


16.多對多,注意兩方都要設定inverse和lazy,cascade只能設為insert-update
   多對多關係中,由於關聯關係是兩張表相互引用,因此在儲存關係狀態時必須對雙方同時儲存。

   group1.getRoles().add(role1);
   role1.getGroups().add(group1);

   session.save(role1);
   session.save(group1);

17.關於vo和po
   vo經過hibernate容量處理,就變成了po(該vo的引用將被容器儲存,並且在session關閉時flush,因此po如果再傳到其它地方改變了,就危險了)
 
   vo和po相互轉換:BeanUtils.copyProperties(anotherUser,user);

18.對於save操作而言,如果物件已經與Session相關聯(即已經被加入Session的實體容器中),則無需進行具體的操作。因為之後的Session.flush過程中,Hibernate
會對此實體容器中的物件進行遍歷,查找出發生變化的實體,生成並執行相應的update
語句。

19.如果我們採用了延遲載入機制,但希望在一些情況下,實現非延遲加
載時的功能,也就是說,我們希望在Session關閉後,依然允許操作user的addresses
屬性
Hibernate.initialize方法可以通過強制載入關聯物件實現這一功能:
這也正是我們為什麼在編寫POJO時,必須用JDK Collection介面(如Set,Map),
而非特定的JDK Collection實現類(如HashSet、HashMap)申明Collection屬性的
原因。

20.事務:從sessionFactory獲得session,其自動提交屬性就已經關閉(AutoCommit=false),此時若執行了jdbc操作,如果不顯式呼叫session.BeginTransaction(),是不會執行事務操作的。

   jdbc transaction:基於同一個session(就是同一個connection)的事務;
   jta  transaction:跨session(跨connection)事務.

   對於jta事務,有三種實現方法:
     A。UserTransaction tx=new InitialContext().lookup("...");
        tx.commit();
     B. 使用hibernate封裝的方法:(不推薦)
        Transaction tx=session.beginTransaction();
        tx.commit();
     C. 使用ejb之sessionBean的事務技持方法,你只要在把需要在釋出描述符中,把需要jta事務的方法宣告為require即可

21.悲觀鎖,樂觀鎖:
   樂觀鎖一般通過version來實現,注意version節點必須出現在id後。


22.Hibernate中,可以通過Criteria.setFirstResult和Criteria.setFetchSize方法設定分頁範圍。
   Query介面中也提供了與其一致的方法,hibernate主要在dialect類中實現在這個功能。


23.cache
   <hibernate-configuration>
 <session-factory>
 ……
  <property name="hibernate.cache.provider_class">
   net.sf.ehcache.hibernate.Provider
  </property> 

  還需對ecache本身進配置
  <ehcache>
 <diskStore path="java.io.tmpdir"/>
 <defaultCache
 maxElementsInMemory="10000" //Cache中最大允許儲存的資料數量
 eternal="false" //Cache中資料是否為常量
 timeToIdleSeconds="120" //快取資料鈍化時間
 timeToLiveSeconds="120" //快取資料的生存時間
 overflowToDisk="true" //記憶體不足時,是否啟用磁碟快取
 />
  </ehcache>

  之後在對映檔案中指定各個對映實體的cache策略
  <class name=" org.hibernate.sample.TUser" .... >
 <cache usage="read-write"/>
 ....
 <set name="addresses" .... >
  <cache usage="read-only"/>
 ....
 </set>
 </class>

 *****************************************************
 Query.list()跟Query.iterate()的不同:
 對於query.list()總是通過一條sql語句獲取所有記錄,然後將其讀出,填入pojo返回;
 但是query.iterate(),則是首先通過一條Select SQL 獲取所有符合查詢條件的記錄的
id,再對這個id 集合進行迴圈操作,通過單獨的Select SQL 取出每個id 所對應的記
錄,之後填入POJO中返回。

 也就是說,對於list 操作,需要一條SQL 完成。而對於iterate 操作,需要n+1
條SQL。,list方法將不會從Cache中讀取資料。iterator卻會。


24.ThreadLocal:它會為每個執行緒維護一個私有的變數空間。實際上,
其實現原理是在JVM 中維護一個Map,這個Map的key 就是當前的執行緒物件,而value則是
執行緒通過ThreadLocal.set方法儲存的物件例項。當執行緒呼叫ThreadLocal.get方法時,
ThreadLocal會根據當前執行緒物件的引用,取出Map中對應的物件返回。

 這樣,ThreadLocal通過以各個執行緒物件的引用作為區分,從而將不同執行緒的變數隔離開
來。


25.Hibernate官方開發手冊標準示例:
  public class HibernateUtil {
private static SessionFactory sessionFactory;
static {
try {
// Create the SessionFactory
sessionFactory = new
Configuration().configure().buildSessionFactory();
} catch (HibernateException ex) {
throw new RuntimeException(
"Configuration problem: " + ex.getMessage(),
ex
);
}
}
public static final ThreadLocal session = new ThreadLocal();
public static Session currentSession() throws HibernateException
{
Session s = (Session) session.get();
// Open a new Session, if this Thread has none yet
if (s == null) {
s = sessionFactory.openSession();
session.set(s);
}
return s;
}
public static void closeSession() throws HibernateException {
Session s = (Session) session.get();
session.set(null);
if (s != null)
s.close();
}


    
26.通過filter實現session的重用:
   public class PersistenceFilter implements Filter
{
protected static ThreadLocal hibernateHolder = new ThreadLocal();
public void doFilter(ServletRequest request, ServletResponse
response, FilterChain chain)
throws IOException, ServletException
{
hibernateHolder.set(getSession());
try
{
……
chain.doFilter(request, response);
……
}
finally
{
Session sess = (Session)hibernateHolder.get();
if (sess != null)
{
hibernateHolder.set(null);
try
{
sess.close();
}
catch (HibernateException ex) {
throw new ServletException(ex);
}
}
}
}
……}

27.Spring的引數化事務管理功能相當強大,筆者建議在基於Spring Framework的應用
開發中,儘量使用容器管理事務,以獲得資料邏輯程式碼的最佳可讀性。
 
public class UserDAO extends HibernateDaoSupport implements IUserDAO
{
public void insertUser(User user) {
getHibernateTemplate().saveOrUpdate(user);
}
}


  上面的UserDAO實現了自定義的IUserDAO介面,並擴充套件了抽象類:
HibernateDaoSupport
HibernateSupport實現了HibernateTemplate和SessionFactory例項的關聯。
HibernateTemplate對Hibernate Session操作進行了封裝,而
HibernateTemplate.execute方法則是一封裝機制的核心