I want to fly higher
          programming Explorer
          posts - 114,comments - 263,trackbacks - 0

          1.關系模型
           關系模型把世界看作是由實體(Entity)和聯系(Relationship)構成的;在關系模型中實體通常是以表的形式來表現的。表的每一行描述
           實體的一個實例,表的每一列描述實體的一個特征或屬性;所謂聯系就是指實體之間的關系,即實體之間的對應關系;
          2.ORM-對象關系映射
           ORM是通過使用描述對象和數據庫之間映射的元數據,將java程序中的對象自動持久化到關系數據庫中;它實現了Java應用中的對象到關系數據庫中的表的自動的(和透明的)持久化;當你開發一個應用程序的時候(不使用O/R Mapping),你可能會寫不少數據訪問層的代碼,用來從數據庫保存,刪除,讀取對象信息等。而這些代碼寫起來總是重復的。
            個人建議:可以去看看Spring的JdbcTemplate
          3.Hibernate-
           提供了強大的對象和關系數據庫映射以及查詢功能。

           持久化Java類必須遵循的原則:
               對JavaBeans風格的屬性實行持久化/getter/setter/
               默認的構造方法->Constructor.newInstance()
               集合類型的屬性,它的類型必須定義為集合的接口
               提供一個標識屬性(identifier property)->如級聯更新等(更新主鍵值的操作,該值由其它表的現有行中的外鍵列引用。在級聯更新中,更新所有外鍵值以與新的主鍵值相匹配)
               ......

               持久化類(POJO)- *.hbm.xml -數據庫結構(schema)【xdoclet/hbm2java(code generator)/SchemaExport(hbm2dll)/Middlegen】

           配置Hibernate:
            開發hibernate3.0必須的包:
             hibernate3.jar
             required:antlr、dom4j、CGLIB、asm、Commons Collections、Commons Logging、 EHCache->oscache
             Hibernate底層還需要Java Transaction API-jta.jar
            將\etc目錄下的log4j.properties復制至Hibernate項目的Classpath下,并修改一下當中的log4j.logger.org.hibernate為error,也就是只在在錯誤發生時顯示必要的訊息
             配置文件.xml/.properties
             hibernate.cfg.xml:

           1<?xml version="1.0" encoding="utf-8"?>
           2   <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 
           3   "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
           4    <hibernate-configuration>
           5        <session-factory>
           6         <!-- 顯示實際操作數據庫時的SQL -->
           7      <property name="show_sql">true</property>
           8      <!-- SQL方言,這邊設定的是MySQL -->
           9      <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
          10       <!-- JDBC驅動程序 -->
          11      <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
          12      <!-- JDBC URL -->
          13       <property name="connection.url">jdbc:mysql://localhost/demo</property>
          14      <!-- 數據庫使用者 -->
          15      <property name="connection.username">root</property>
          16      <!-- 數據庫密碼 --> 
          17       <property name="connection.password">root</property>
          18         <!-- 以下設置對象與數據庫表格映像文件 -->
          19     </session-factory>
          20    </hibernate-configuration>
          21


               *.hbm.xml-告訴 Hibernate您所定義的*實例如何映射至數據庫表,以Use為例:user.hbm.xml-
              

           1 <?xml version="1.0" encoding="utf-8"?>
           2  <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"     
           3  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
           4   <hibernate-mapping>  
           5    <class name="com.db.hibernate.demo.User" table="user">    
           6     <id name="id" column="id" type="java.lang.Integer">
           7     <!-- 主鍵的生成方式由Hibernate根據數據庫Dialect的定義來決定 -->
           8     <generator class="native" /> 
           9     </id>    
          10     <property name="name" column="name" type="java.lang.String" />    
          11     <property name="age" column="age" type="java.lang.Integer" />  
          12    </class>
          13  </hibernate-mapping>
          14


              需要在Hibernate配置文件hibernate.cfg.xml中指明映像文件的位置
           詳見eclipse的db工程
          4.配置文件的問題:
           1.The content of element type "session-factory" must match "(property*,mapping*,(class-cache|collection-cache)*,event*,listener*)".
            解決:1.可能是文件編碼問題;我的hibernate.cfg.xml是從ppt拷貝出來的,文件編碼有問題;從正確的機器上拷貝一份文件或
            者嘗試重新編碼或者從網上拷貝一份正確的然后修改(正確的方法是參考etc目錄下的xml模板)
             2.可能是元素(element type)的順序問題
             3.可以將hibernate-configuration-3.0.dtd下載下來,對比一下,看哪里出錯
           2.hibernate.cfg.xml和*.hbm.xml目前只能放到src根目錄下,放到其他目錄總報錯
           3.關于xml dtd,正常下載的jar包中都會有dtd文件的,如hibernate-configuration-3.0.dtd;dom4j解析的時候會優先驗證本地,如果本地有,則不會連接dtd指定的服務器地址;如果沒有的話,可以去那地址下載dtd,放在本地或者將地址改為本地dtd的位置;當然eclipse也由一個選項,window->preference->xml catalog,可以添加;詳見xml選項
          5.Criteria
           Criteria對SQL進行封裝,對于不甚了解SQL的開發人員來說,使用Criteria也可以輕易的進行各種數據的檢索;Expression設定查詢條件(Expression已被廢棄,eclipse中添加hibernate的javadoc,方便查看)Criteria是對象導向式的查詢方式,讓不了解SQL的開發人員也可以輕易進行各項查詢;但Criteria的API目前還不是很完善;Hibernate鼓勵的查詢方式,是透過HQL(Hibernate Query Language)來進行.
          6.Query接口
          7.hibernate配置文件-hibernate.cfg.xml(提供較好的結構與配置方式,hibernate建議使用,默認)/hibernate.properties
               注意:XML配置文件的位置必須在Classpath下;默認的XML配置文件名稱是hibernate.cfg.xml;你可以自己指定配置文件:
               new Configuration().configure().configure("db.cfg.xml");
           在Hibernate下載檔案中的etc目錄下,有hibernate.cfg.xml與hibernate.properties可供設定參考properties檔案中不包括映射文件的名稱,需要編程方式:
           Configuration cfg = new Configuration().addClass("user.hbm.xml") .addClass(com.db.hibernate.demo.User.class);

           hibernate.properties:
           hibernate.show_sql = true
           hibernate.dialect = org.hibernate.dialect.MySQLDialect
           hibernate.connection.driver_class = com.mysql.jdbc.Driver
           hibernate.connection.url = jdbc:mysql://localhost/demo
           hibernate.connection.username = root
           hibernate.connection.password = root
          8.Configuration-
           Configuration的實例管理Hibernate的配置信息,通常用于建立SessionFactory
           SessionFactory sessionFactory = config.buildSessionFactory();
          9.SessionFactory-
           SessionFactory一旦建立,就被賦予當時Configuration的配置信息;即使改變Configuration也不會影響之前已建立的該實例,而會新建SessionFactory中包括了數據庫配置及映射關系,它的建立相當復雜,所以使用時需考慮到重用已建立的SessionFactory實例SessionFactory是被設計為線程安全的(Thread-safe)
          10.設定數據庫連接-
           設定connection.pool_size是Hibernate默認的連接池設定;通常只用于開發階段測試之用
           <!-- Hibernate 預設的Connection pool -->     
           <property name="connection.pool_size">2</property> 
               使用C3P0連接池,需要包含c3p0-*.jar;也可以使用Proxool或DBCP連接池(etc目錄hibernate.properties中的配置例子來參考)使用Tomcat的話,您也可以通過它提供的DBCP連接池來取得連接-配置中加入connection.datasource屬性
          11.hibernate緩存
           Hibernate中Session level緩存會在使用主鍵加載資料或是延遲初始(Lazy Initialization) 時作用Session level緩存,Session會維護一個Map容器
           通過evict()將某個對象從緩存中移去,可以使用clear()清除緩存中的所有對象
           可以通過session的load方法和==來判斷是否存在緩存

           Session在使用save()儲存對象時,會將要儲存的對象納入Session level緩存管理,在進行大量數據儲存時,緩存中的實例大量增加最后會導致OutOfMemoryError,可以每隔一段時間使用Session的 flush()強制儲存對象,并使用clear()清除緩存

           1 1 Session session = sessionFactory.openSession();
           2 2  Transaction tx = session.beginTransaction(); 
           3 3  while(.)
           4 4  
           5 5   // 大量加載對象時的循環示意    
           6 6   .    
           7 7   session.save(someObject);    
           8 8   if(count % 100 == 0
           9 9   
          1010    // 每100筆資料        
          1111    session.flush(); 
          1212    // 送入數據庫        
          1313    session.clear(); 
          1414    // 清除緩存    
          1515   }

          1616  }
           
          1717  tx.commit();
          1818  session.close();
          19


            配置中hibernate.jdbc.batch_size來控制每多少筆資料就送至數據庫(MySQL中則不支持這個功能,sqlserver/oracle支持)
          12.事務
           事務是一組原子(Atomic)操作(一組SQL執行)的工作單元;事務中的所有原子操作,不是全部執行成功,就是全部失?。词怪挥幸粋€失敗,所有的原子操作也要全部撤消(回滾))JDBC中通過Connection的setAutoCommit和Commit方法管理事務,異常則回滾;Hibernate本身沒有事務管理功能,它依賴于JDBC或JTA(java transaction api)的事務管理功能;默認是使用JDBC事務管理
           配置中添加:hibernate.transaction.factory_class屬性來指定Transaction的工廠類別
           <property name="hibernate.transaction.factory_class"> org.hibernate.transaction.JDBCTransactionFactory</property> 
           Hibernate基于JDBC的事務管理只是對JDBC作了個簡單的封裝:

           1 try 
           2  {     
           3   session = sessionFactory.openSession();      
           4   Transaction tx = session.beginTransaction();     
           5   .      
           6   tx.commit();  // 必須commit才會更新數據庫
           7  }
           
           8  catch(HibernateException e)
           9  {    
          10   tx.rollback(); 
          11  }


            在一開始的openSession()取得Session時,JDBC的Connection實例之AutoCommit就被設定為false,在 beginTransaction()時,會再度檢查Connection實例的AutoCommit為false,在操作過程中,最后要commit (),否則的話對數據庫的操作不會有作用,如果操作過程中因發生例外,則最后commit()不會被執行,之前的操作取消,執行rollback()可撤消之前的操作。要使用MySQL中的事務處理,必須建立事務表類型的表格例如InnoDB的表格
          13.映射文件
           Hibernate 中將對象與數據庫表格映射關系連接起來的是映射文件;通常以*.hbm.xml作為文件名稱;手工撰寫;通過工具程序從數據庫表格自動生成;通過工具程序從Java類自動生成三部分:類名稱與表格名稱的映射;id屬性與主鍵的映射;類屬性與表格字段的映射

           1<?xml version="1.0" encoding="utf-8"?>
           2 <!DOCTYPE hibernate-mapping       PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"       
           3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
           4 <hibernate-mapping>    
           5  <!--類別名稱與表格名稱映像-->    
           6 <class name="onlyfun.caterpillar.User" table="user">      
           7  <!--id與主鍵映像-->      
           8  <id name="id" column="id" type="java.lang.Integer">        
           9   <generator class="native"/>      
          10  </id>      
          11  <!--類別屬性與表格字段的映像-->      
          12  <property name="name" column="name" type="java.lang.String"/>      
          13  <property name="age" column="age" type="java.lang.Integer"/>    
          14 </class>  
          15 </hibernate-mapping> 
          16


            注:
            1.Java的數據類型與數據庫的數據類型并不是一對一對應的,為此Hibernate提供它自己的數據類型,作為Java數據類型與數
            據庫數據類型的連接類型
            2.<generator>設定主鍵的生成方式;“native”表示由Hibernate自動根據Dialect選擇采用 identity、hilo、sequence等作為主鍵生成方
            式;可以考慮采用uuid由Hibernate根據128位UUID算法(128- bit UUID algorithm)生成16進位制數值,并編碼為32位長度的字符
            串
          14.基本API
               1.Session-是Hibernate操作的基礎;不是設計為線程安全;一個Session由一個線程使用;
               Hibernate在對數據庫進行操作之前,必須先取得Session實例,相當于JDBC在對數據庫操作之前,必須先取得Connection實例;過Session,可以對數據庫進行新增、刪除、更新;使用save()新增一條記錄;使用get()或load()方法取得id為1的記錄-User user = (User) session.get(User.class, new Integer(1));
           如果未能發現相符合的記錄,則get()方法會返回null,而load()方法會丟出ObjectNotFoundException;在高級的應用中,load()方法可以返回代理對象,并可充分利用緩沖機制
           Hibernate 3中,取消了find()方法,您必須通過Query或Criteria來進行記錄查詢
               使用delete()刪除資料
            1 User user = (User) session.get(User.class, new Integer(1));
             session.delete(user);
            2 Query q=session.createQuery(“delete User u where u.id=1”);
             q.executeUpdate();
            3 Session.delete(“from User u where u.id=1”);
               使用update()方法將對象中的資料更新至對應的數據表中
           Session提供了一個saveOrUpdate()方法:由定義映射文件時,設定<id>卷標的unsaved-value來決定
           Session如同在編寫JDBC時需關心 Connection的管理,以有效的方法創建、利用與回收Connection,以減少資源的消耗,增加系統
           執行效率一樣;SessionFactory是線程安全的(Thread-safe),然而Session則不是設計為線程安全的,所以試圖讓多個執行緒共享一個
           Session,將會發生資料共享而發生混亂的問題
           2.Session管理
            使用了ThreadLocal類來建立一個Session管理的輔助類,這是Hibernate的Session管理一個廣為應用的解決方案
            Thread-Specific Stroage模式可以有效隔離線程所使用的資源,所以避開Session的多線程之間的資源共享問題
            ThreadLocal是*Thread-Specific Storage 模式*的一個運用實例
            Hibernate會在真正需要數據庫操作時才(從連接池中)取得Connection
            在Web應用程序中,可以藉由Filter來進行Session管理,在需要的時候開啟Session,并在Request結束之后關閉Session
           3.Criteria基本查詢
            Criteria對SQL進行封裝,讓開發人員可以用對象的方式來對數據庫進行操作
            Criteria criteria = session.createCriteria(User.class);
            // 查詢user所有字段
            List<User> users = criteria.list();
            Criteria實際上只是個容器,如果想要設定查詢條件,則要使用add()方法加入Restrictions的條件限制
            例如查詢age大于20且小于40的資料:

          1Criteria criteria = session.createCriteria(User.class);
          2  criteria.add(Restrictions.gt("age"new Integer(20)));//greater than >
          3  criteria.add(Restrictions.lt("age"new Integer(40)));//lesser than <
          4  List<User> users = criteria.list();


            也可以使用邏輯組合來進行查詢-criteria.add(Restrictions.or(Restrictions.eq(), Restrictions.isNull())
            sqlRestriction()方法來提供SQL語法作限定查詢
            criteria.add(Restrictions.sqlRestriction("{alias}.name LIKE (?)", "cater%", Hibernate.STRING));//alias別名
            在SQL撰寫時,不必再寫WHERE
            criteria.add(Restrictions.sqlRestriction("{alias}.age BETWEEN (?) AND (?)", ages, types));
            Restrictions的幾個常用限定查詢方法:eq/allEq/gt/ge/lt/le/between/like/in/and/or/sqlRestriction
           4.Criteria高級查詢
            使用Criteria進行查詢,并使用Order對結果進行排序
            criteria.addOrder(Order.asc("age"));//desc()
            setMaxResults()方法可以限定查詢回來的記錄數;setFirstResult()設定傳回查詢結果第一個記錄的位置
            這兩個配合起來,就可以實現簡單的分頁
            對查詢結果進行統計動作,使用Projections的avg()、rowCount()、count()、max()、min()、countDistinct()等方法
            criteria.setProjection(Projections.avg("age"));
            可以配合Projections的groupProperty()來對結果進行分組
            criteria.setProjection(Projections.groupProperty("age"));
            想結合統計與分組功能,則可以使用ProjectionList

          1ProjectionList projectionList = Projections.projectionList();
          2   projectionList.add(Projections.groupProperty("age"));
          3   projectionList.add(Projections.rowCount()); 
          4   Criteria criteria = session.createCriteria(User.class);
          5   criteria.setProjection(projectionList);


            使用Example對象,可以將一個已知的對象作為查詢的依據
            criteria.add(Example.create(user));
            Criteria可以進行復合查詢
            Criteria與Session綁定,其生命周期跟隨著Session結束而結束;使用Criteria時進行查詢時,每次都要于執行時期動態建立對象
            能夠重復使用Criteria對象,在Hibernate 3.0中新增了DetchedCriteria對象;您可以先建立DetchedCriteria實例,并加入各種查詢條
            件,并于需要查詢時再與Session綁定,獲得一個綁定Session的Criteria對象

          1// 先建立DetchedCriteria對象
          2   DetachedCriteria detchedCriteria=DetachedCriteria.forClass(User.class);
          3   // 加入查詢條件
          4   detchedCriteria.add(Restrictions.ge("age",new Integer(25)));        
          5   Session session = sessionFactory.openSession();
          6   // 綁定Session并返回一個Criteria實例
          7   Criteria criteria = detchedCriteria.getExecutableCriteria(session); 
          8


              5.Query接口
            使用org.hibernate.Query接口的實例來進行查詢;
            透過Query接口,您可以先設定查詢參數,使用setXXX()等方法,將指定的參數值填入,而不用每次都撰寫完整的HQL
            在設定參數值時,必須依照 ? 所設定的順序,并使用對應類型的setXXX()方法
            也可以使用命名參數(Named Parameter)
            將HQL撰寫在程序之;避免硬編碼(Hard code)在程序之中,在需要修改HQL時就很方便;
            在*.hbm.xml中使用<query/>卷標,并在<![CDATA[與]] >之間撰寫HQL,撰寫的位置是在</hibernate-mapping>之前
            (CDATA-character data)

           1 <?xml version="1.0" encoding="utf-8"?>
           2  <!DOCTYPE hibernate-mapping      
           3  PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"       
           4  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
           5 <hibernate-mapping>    
           6  <class name="model.User" table="user">       
           7   <id name="id" column="id“ type="java.lang.Integer">         
           8   <generator class="native"/>      
           9   </id>      
          10   <property name="name" column="name" type="java.lang.String"/>   
          11   <property name="age" column="age" type="java.lang.Integer"/>   
          12  </class>    
          13  <query name=“model.QueryUser">       
          14   <![CDATA[
          15   select user.name from User as user where user.age >:minAge 
          16   ]]>         
          17  </query>  
          18 </hibernate-mapping>
          19


             <query>的name屬性用來設定查詢外部HQL時的名稱依據
            Query query = session.getNamedQuery(“model.QueryUser");
            query.setInteger("minAge", 25); 
          15.HQL
           1.HQL基本查詢
            查詢指定類對應表格的所有記錄
            Query query = session.createQuery("from User"); //也可以指定類的全稱
            List names = query.list();
            HQL本身不區分大小寫,不過要注意類的名稱必須區分大小寫
            Hibernate會自動判定繼承關系,如果查詢的類是某類的父類,則會返回與父類、子類對應的所有表格記錄
            針對某個屬性作查詢-Query query = session.createQuery("select user.name from User as user"); 
            查詢兩個以上的屬性,查詢的結果會以數組的方式返回
            Query query = session.createQuery("select user.age, user.name from User as user"); Object[] obj = (Object[]) iterator.next();
            如果User類提供有適當的構建方法,則可以在使用HQL時直接指定新建一個對象傳回-
            Query query = session.createQuery("select new User(user.name, user.age) from User as user");
            List names = query.list();User user= (User) iterator.next(); //這個返回的User實例并未與數據庫有任何關聯
            使用distinct去除資料重復的記錄-Query query = session.createQuery("select distinct user.age from User as user");
            在HQL中使用函數-Query query = session.createQuery("select count(*) from User as user"); 
            使用avg()取得屬性的平均值-Query query = session.createQuery("select avg(user.age) from User as user");
            使用upper()函數將字符串轉為大寫:Query query = session.createQuery("select upper(user.name) from User as user"); 
           2.where 子句
            使用where子句來限定查詢的條件,除了 = 運算之外,還有 >、>=、<、<=、!= 或 <>等比較運算
            Query query = session.createQuery("from User user where user.name=‘cjy'"); 
            where子句上進行表達式-Query query = session.createQuery("from User user where (user.age / 10 = 3)");
            在where子句上使用and、or-Query query = session.createQuery("from User user where (user.age > 20) and (user.name = ‘cjy')");
            is not nullL與is null則可以測試字段值是否為空值Query query = session.createQuery("from User user where user.name is not null");
            between可以測試字段值是否在指定的范圍之內-session.createQuery("from User user where user.age between 20 and 30");
            使用in或not in來測試字段值是否在您指定的集合中-session.createQuery("from User user where user.name in(‘cjy', ‘abc')");
            like或not like可以讓您進行模糊條件搜尋-session.createQuery("from User user where user.name like ‘c%'");
            查詢結果使用order by進行排序-session.createQuery("from User user order by user.age");
            可使用desc反排序-session.createQuery("from User user order by user.age desc");
            同時指定兩個以上的排序方式-
            session.createQuery("from User user order by user.age desc, user.name");//先按照"age"反序排,"age"相同,則按照"name"順序排列
            使用GROUP BY子句,自動將指定的字段依相同的內容群組-
            session.createQuery("select user.sex, avg(user.age) from User user group by user.sex");
            結合having子句-session.createQuery("select user.sex, avg(user.age) from User user group by user.sex having avg(user.age) > 20");
            在Hibernate 3中,HQL新增了update與delete語句,可以直接使用HQL指定更新或刪除
            update子句進行更新-session.createQuery("update User set name=‘abc' where name=‘cjy'");query.executeUpdate();
            delete子句進行資料刪除-session.createQuery("delete User where name=‘cjy'");query.executeUpdate();
          16.SQL支持
           Hibernate提供了對SQL的支持,您可以指定您所要建立的SQL,并將實體類與資料表格關聯;
            // SQL,并指定別名為user

          1String sql = "select {user.*} from User user where user.age > 20";
          2  Session session = sessionFactory.openSession();
          3  // 建立 SQLQuery
          4  SQLQuery sqlQuery = session.createSQLQuery(sql);
          5  // 將別名user與實體類User關聯在一起
          6  sqlQuery.addEntity("user", User.class);
          7  Iterator iterator = sqlQuery.list().iterator();
          8


             addEntity()是將實體類與別名連結在一起的方法,大括號指定要查詢的記錄
           也可以將SQL語句定義在映射文件中*.hbm.xml
           <sql-query name="model.QueryUser">    
           <![CDATA[                   
            select {user.*} from User user where user.age > 20             
           ]]>             
           <return alias="user" class="model.User"/>  
           </sql-query> 
            Query query = session.getNamedQuery(“model.QueryUser");
            Iterator iterator = query.list().iterator();
            可以設定查詢參數;
             <sql-query name=“model.QueryUser">
             <![CDATA[
              select {user.*} from User user where user.age > :age
             ]]>
             <return alias="user" class=“model.User"/>
             </sql-query>
              Query query = session.getNamedQuery("model.QueryUser");
              query.setInteger("age", 20); 
           Hibernate 3的映射文件中新增了<sql-insert>、<sql-update>與<sql-delete>三個卷標,您可以在這三個卷標中使用SQL自定義您的
           INSERT、UPDATE、DELETE

          1 <sql-insert>       
          2   INSERT INTO user (name, age) VALUES (?, ?)              
          3  </sql-insert>     
          4  <sql-update>       
          5   UPDATE user SET name=?, age=?, WHERE id=?              
          6  </sql-update>      
          7  <sql-delete>       
          8    DELETE FROM user WHERE id=?              
          9  </sql-delete>

              
            ? (參數) 對應的順序是映像文件中屬性出現的順序
          17.映射基礎
               Hibernate中的實體對象可以分為三種狀態:Transient、Persistent、Detached。
               Transient-如User類所衍生出之對象,在還沒有使用save()之前都是暫存對象,這些對象還沒有與數據庫發生任何的關系,不對應于數據庫中的任一條記錄。 
               Persistent-當對象與數據庫中的記錄有對應關系,并且與Session實例有關聯而Session 實例尚未關閉(close),則它是在Persistent狀態;Persistent狀態的對象對應于數據庫中的一條記錄,對象的id值與記錄的主鍵值相同,并且Session實例尚未失效;在這期間您對對象的任何狀態變動,在Session實例關閉(close)或Transaction實例執行commit()之后,數據庫中對應的記錄也會跟著更新Session實例關閉(close),則Persistent狀態的對象會成為Detached狀態;使用Session的實例delete()方法刪除記錄,Persistent狀態的對象由于失去了對應的記錄,則它會成為Transient狀態。
               Detached-Detached狀態的對象,其id與數據庫的主鍵值對應;Detached狀態的對象之任何屬性變動,不會對數據庫中的記錄造成任何的影響;Detached狀態的對象可以使用update()方法使之與數據庫中的對應記錄再度發生關聯,此時Detached狀態的對象會變為 Persistent狀態。

               Transient與Detached狀態的對象未受Hibernate持久層管理員管理,對這兩個狀態的對象作任何屬性變動,不會對數據庫中的記錄有任何的影響;而Persistent狀態的對象受Hibernate持久層管理,對對象的屬性變動,在Session實例關閉(close)或 Transaction實例執行commit()之后,數據庫中對應的記錄也會跟著更新。在對象為Persistent時,如果對象的屬性發生變化,并且尚未提交之前,對象所攜帶的資料稱之為Dirty Data,Hibernate會在持久層
           維護對象的最近讀取版本,并在資料提交時檢查兩個版本的屬性是否有變化,如果有的話,則將數據庫中的記錄進行更新。

           對象識別:
            要有必要比較透過查詢后兩個對象的資料是否相同(例如當對象被儲存至Set時)您必須重寫 equals()與hashCode()
            重寫方法之一,equals()與hashCode()的方法是根據數據庫的identity,就是透過getId()方法取得對象的id值并加以比較

           1public class User 
           2  {    
           3   .     
           4   public boolean equals(Object o) 
           5   {        
           6    if(this == o) return true;       
           7    if(id == null || !(o instanceof User)) 
           8     return false;         
           9    final User user == (User) o;        
          10    return this.id.equals(user.getId());    
          11    }
               
          12   public int hasCode() 
          13   {        
          14    return id == null ? System.identityHashCode(this):id.hashcode();    
          15   }
           
          16  }

          17

            
            上面的例子是個不被鼓勵的例子,因為當一個對象被new出來而還沒有save()時,它并不會被賦予id值,這時候就不適用這
            個方法;
           比較被采用的方法是根據對象中真正包括的的屬性值來作比較;
           可以使用org.apache.commons.lang.builder.EqualsBuilder與 org.apache.commons.lang.builder.HashCodeBuilder來協助定義equals()與
           hashCode();
            Return new EqualsBuilder().append(this.name,user.getName()).append(this.phone, user.getPhone()).isEquals();
            return new HashCodeBuilder().append(this.name).append(this.phone).toHashCode();
          18.實體映射/集合映射/關系映射/繼承映射/緩存/鎖定/回調與攔截/工具
          19.Annotation-
           可以不通過*.hbm.xml,完全通過annotation搞定
           hibernate.cfg.xml-
           <!-- 以下設置對象與數據庫表格映像類別 -->
                  <mapping class="com.db.hibernate.demo.User"/>

           實體標識,主鍵生成,以及相關映像,都可以使用Annotation來完成;

           1@Entity
           2 @Table(name="user"// 非必要,在表格名稱與類別名稱不同時使用
           3 public class User
           4 {
           5  @Id
           6  @GeneratedValue(strategy=GenerationType.AUTO)
           7   private Integer id;
           8
           9  @Column(name="name"// 非必要,在字段名稱與屬性名稱不同時使用
          10  private String name;
          11  
          12  @Column(name="age"
          13  private Integer age; // 非必要,在字段名稱與屬性名稱不同時使用
          14    
          15   // 必須要有一個預設的建構方法
          16    // 以使得Hibernate可以使用Constructor.newInstance()建立對象
          17   public User() {    }
          18 }

          19


            注意:import javax.persistence.*中的注解

           使用Annotation時,需要的是AnnotationConfiguration類;

          1// 需要AnnotationConfiguration讀取Annotation訊息
          2  Configuration config = new AnnotationConfiguration().configure();
          3  // 根據 config 建立 SessionFactory
          4  // SessionFactory 將用于建立 Session
          5   SessionFactory sessionFactory = config.buildSessionFactory();

           

          posted on 2011-12-26 23:11 landon 閱讀(1879) 評論(1)  編輯  收藏 所屬分類: 學習筆記

          FeedBack:
          # re: Hibernate學習筆記
          2015-03-09 13:42 | zuidaima
          java hibernate demo使用實例教程源代碼下載:http://zuidaima.com/share/khibernate-p1-s1.htm  回復  更多評論
            

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 龙门县| 潮州市| 铜鼓县| 密云县| 新闻| 浦县| 华宁县| 江都市| 登封市| 理塘县| 凤庆县| 台山市| 平顶山市| 封开县| 渑池县| 定远县| 行唐县| 图片| 卫辉市| 准格尔旗| 平定县| 永丰县| 阿克苏市| 合川市| 鹤岗市| 绵阳市| 抚顺市| 西林县| 扎兰屯市| 夏津县| 格尔木市| 永春县| 嘉鱼县| 三穗县| 呼和浩特市| 玉环县| 明光市| 桐柏县| 宁津县| 上犹县| 武川县|