posts - 19, comments - 53, trackbacks - 0, articles - 283
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
           

          一、HibernateORMObject Relation Mapping)對(duì)象關(guān)系映射框架

          常用的ORM框架有:HibernateTopLinkOJB

          Hibernate 框架完全是進(jìn)行對(duì)象的操作,不再會(huì)有對(duì)字段、屬性的操作。如Hibernate 刪除則是刪除一個(gè)對(duì)象,更新則是對(duì)某一個(gè)對(duì)象狀態(tài)進(jìn)行更新

          小貼士:應(yīng)用Hibernate開發(fā)時(shí),可與JDBC相聯(lián)想

          二、開發(fā)流程:

          1.Domain Object ----mapping -----db(官方推薦)

          2.DB開始,用工具生成mappingDomain Object(使用較多)

          3.由映射文件開始

          Domain Object 限制:

          1.默認(rèn)的構(gòu)造方法(必須的)

          2.有無意義的標(biāo)示符id(主鍵)(可選)

          3.final,對(duì)懶加載有影響

          三、需要一個(gè)工具類,只加載一次 hibernate.cfg.xml 文件

          package cn.itcast.hibernate;

          import org.hibernate.Session;

          import org.hibernate.SessionFactory;

          import org.hibernate.cfg.Configuration;

          publicfinalclass HibernateUtil 
          {

              
          private HibernateUtil() {}

              privatestatic SessionFactory sf 
          = null

              
          static {

                  Configuration cfg 
          = new Configuration();

                  cfg.configure();

          //cfg.configure(new File("filename")); //指定配置文件的路徑,不指定則默認(rèn)

                  sf 
          = cfg.buildSessionFactory();

              }
             

              publicstatic SessionFactory getSessionFactory() 
          {

                  returnsf;

              }
             

              publicstatic Session getSession() 
          {

                  returnsf.openSession();

              }


          }

           

          小貼士:將java類與hibernate源碼綁定

          四、Mysql 有多種引擎:

              MyISAM:5.0以前的缺省引擎,效率高但不支持事務(wù)。

              InnoDB:支持事務(wù),則Hibernate操作時(shí)需要開啟事務(wù),進(jìn)行操作后提交事務(wù),這樣才能將數(shù)據(jù)持久化:

          Transaction tx = s.beginTransaction();//開啟事務(wù)

                  User user = new User();

                  user.setName("name");

                  user.setBirthday(new Date());

                  s.save(user);

          tx.commit(); //事務(wù)提交

          五、Hibernate 核心接口概述:

          Configuration:

          負(fù)責(zé)管理Hibernate的配置信息,這些信息由配置文件提供,包括如下內(nèi)容:

          1.Hibernate運(yùn)行的底層信息:數(shù)據(jù)庫的URL、用戶名、密碼、JDBC驅(qū)動(dòng)類等,數(shù)據(jù)庫Dialect,數(shù)據(jù)庫連接池等。

          2.Hibernate映射文件(*.hbm.xml

          調(diào)用代碼:

          1.屬性文件(hibernate.properties)

          Configuration cfg = new Configuration();

          cfg.addClass(XXX.class);//該方法加載XXX.hbm.xml

          cfg.addResource();

          2.XML文件(hibernate.cfg.xml

          Configuration cfg = new Configuration();

          cfg.configure();

          SessionFactory:

          1.應(yīng)用程序從SessionFactory(會(huì)話工廠)里獲得Session(會(huì)話)實(shí)例。它在多個(gè)應(yīng)用線程間進(jìn)行共享。通常情況下,整個(gè)應(yīng)用只有唯一的一個(gè)會(huì)話工廠---例如在應(yīng)用初始化時(shí)被創(chuàng)建。然而,如果你使用Hibernate訪問多個(gè)數(shù)據(jù)庫,你需要每個(gè)數(shù)據(jù)庫使用一個(gè)會(huì)話工廠。

          2.會(huì)話工廠緩存了生成的SQL語句和Hibernate在運(yùn)行時(shí)使用的映射元數(shù)據(jù)。

          3.調(diào)用代碼:

          privatestatic SessionFactory sf = null

          static {

              Configuration cfg = new Configuration();

              cfg.configure();

              sf = cfg.buildSessionFactory();

          }

          Session

          1.Session不是線程安全的,它代表與數(shù)據(jù)庫之間的一次操作會(huì)話

          2.Session也稱為持久化管理器,因?yàn)樗桥c持久化有關(guān)的操作接口

          3.Session通過SessionFactory打開,在所有的工作完成后,需要關(guān)閉

          4.Session緩存其管理的持久化對(duì)象

          5.調(diào)用代碼:

          Session session sessionFactory.openSession();

          Transaction:

          1.它將應(yīng)用代碼從底層的事務(wù)實(shí)現(xiàn)中抽象出來---這可能是一個(gè)JDBC事務(wù),一個(gè)JTA用戶事務(wù)或者甚至是一個(gè)公共對(duì)象請(qǐng)求代碼結(jié)構(gòu)(CORBA---允許應(yīng)用通過一組一致的API控制事務(wù)邊界

          2.這有助于保持Hibernate應(yīng)用在不同類型的執(zhí)行環(huán)境或容器中的可移植性

          3.Hibernate提供的事務(wù)提交模式默認(rèn)為非自動(dòng)提交模式(默認(rèn):autoCommit=false),因此使用Hibernate進(jìn)行操作時(shí)(增、刪、改)必須顯示的調(diào)用TransactionAPI

          4.調(diào)用代碼:

          Transaction tx = session.beginTransction();

          Tx.commit()/rollback();

          Query/Criteria:

          1.Query接口封裝了Hibernate強(qiáng)大的對(duì)象查詢能力,同時(shí)也支持?jǐn)?shù)據(jù)庫的更新操作

          2.提供了動(dòng)態(tài)查詢的參數(shù)綁定功能

          3.提供list(),iterator(),scroll()等對(duì)象導(dǎo)航方法

          4.提供uiqueResult()方法獲取單獨(dú)的對(duì)象

          5.提供executeUpdate()方法來執(zhí)行DML語句

          6.提供了可移植的分頁查詢方法

          Session

          1、savepresist保存數(shù)據(jù),persist在事務(wù)外不會(huì)產(chǎn)生insert語句。

          2、delete,刪除對(duì)象

          3、update,更新對(duì)象,如果數(shù)據(jù)庫中沒有記錄,會(huì)出現(xiàn)異常,脫管對(duì)象如屬性改變需要保存,則調(diào)用update方法

          4、get,根據(jù)ID查,會(huì)立刻訪問數(shù)據(jù)庫

          5、load,根據(jù)ID查,(返回的是代理,不會(huì)立即訪問數(shù)據(jù)庫)

          6、saveOrUpdate,merge(根據(jù)IDversion的值來確定是否是saveupdate),調(diào)用merge你的對(duì)象還是托管的。當(dāng)不知該對(duì)象的狀態(tài)時(shí)可調(diào)用該方法

          小貼士:瞬時(shí)對(duì)象id無值,脫管對(duì)象有值,hibernate通過該方式判斷對(duì)象的狀態(tài)

          7、lock(把對(duì)象變成持久對(duì)象,但不會(huì)同步對(duì)象的狀態(tài))

          六、Hibernate中對(duì)象的狀態(tài):

          狀態(tài)的參考:數(shù)據(jù)庫中是否有記錄;是否有session關(guān)聯(lián)

          1、瞬時(shí)(transient):數(shù)據(jù)庫中沒有數(shù)據(jù)與之對(duì)應(yīng),超過作用域被JVM垃圾回收器回收,一般是new出來且session沒有關(guān)聯(lián)的對(duì)象

          2、持久(persistent):數(shù)據(jù)庫中有數(shù)據(jù)與之對(duì)應(yīng),當(dāng)前session有關(guān)聯(lián),并且相關(guān)聯(lián)的session沒有關(guān)閉,事務(wù)沒有提交;持久對(duì)象狀態(tài)發(fā)生改變,在事務(wù)提交時(shí)會(huì)影響到數(shù)據(jù)庫(hibernate能檢測(cè)到)

          3、脫管(detached):數(shù)據(jù)庫中有數(shù)據(jù)與之對(duì)應(yīng),但當(dāng)前沒有session與之關(guān)聯(lián);托管對(duì)象狀態(tài)發(fā)生改變,hibernate不能檢測(cè)到

          對(duì)象在的狀態(tài)轉(zhuǎn)化:
              



          當(dāng)對(duì)象被
          savecommit后,Hibernate Session 任然能察覺到對(duì)象,如果此時(shí)對(duì)象屬性發(fā)生改變,則數(shù)據(jù)庫中持久化的值同樣被改變,如:

              //標(biāo)準(zhǔn)方法

              static void addUser(User user) {

                  Session s = null;

                  Transaction tx = null;

                  try {

                      s = HibernateUtil.getSession();

                      tx = s.beginTransaction();

                      s.save(user);

          user.setName("new name");

                      tx.commit();

                  } catch (HibernateException e) {

                      if (tx != null) {

                          tx.rollback();

                      }

                      throw e;

                  } finally {

                      if (s != null)

                          s.close();

                  }

          }

          user對(duì)象在數(shù)據(jù)庫中最終持久化的name=="new name",如果在commit之前修改過的屬性,將會(huì)在commit時(shí)候統(tǒng)一對(duì)對(duì)象進(jìn)行update

          七、Hibernate Query LanguageHQL)和CriteriaQBC

          HQL:面向?qū)ο蟮牟樵冋Z言,與SQL不同,HQL中的對(duì)象名是區(qū)分大小寫的(除了JAVA類和屬性其他部分不區(qū)分大小寫);HQL中查的是對(duì)象而不是和表,并且支持多態(tài)HQL主要通過Query來操作,Query的創(chuàng)建方式:

          Query q = session.createQuery(hql);

          1.from Person

          2.from User user where user.name=:name

          3.from User user where user.name=:name and user.birthday<:birthday

          static void query(String name) {

                  Session s = null;

                  try {

                      s = HibernateUtil.getSession();

                      String hql = "from User as user where user.name=?"//from Object ... 因?yàn)镠QL支持多態(tài),所以執(zhí)行 from Object時(shí),將會(huì)將所有的表都查一遍

                      /**

                       * 當(dāng)查詢條件有多個(gè)的時(shí)候,則參數(shù) "?" 將會(huì)有多個(gè),這樣對(duì)我們的維護(hù)帶來極大不便,在HQL中我們利用命名參數(shù)處理

                       * "from User as user where user.name=?" -->> "from User as user where user.name=:n"

                       * query.setString("n", name);

                       * 經(jīng)過這樣設(shè)置后在多條件情況下,我們不需要再顧及參數(shù)的先后順序了

                       */

                      Query query = s.createQuery(hql);

                      query.setString(0, name);

                     

                      /**

                       * Hibernate 分頁: 200-210

                       * query.setFirstResults(200);

                       * query.setMaxResults(10);

                       * 這樣的分頁,為數(shù)據(jù)庫的移植做到了很好的兼容,根據(jù)數(shù)據(jù)庫設(shè)置的方言來判斷

                       */

                      List<User> list = query.list();

                          //Object obj = query.uniqueResult(); 當(dāng)我們確定返回的結(jié)果集就一條記錄,則可調(diào)用此方法,如有多條,則會(huì)報(bào)異常

                      for(User user : list) {

                          System.out.println(user.getName());

                      }

                  } finally {

                      if (s != null) {

                          s.close();

                      }

                  }

          }

          HQL SQL 查詢的區(qū)別:

          HQL根據(jù)屬性名查對(duì)象,SQL根據(jù)字段查表

          Creteria:Criteria是一種比HQL更面向?qū)ο蟮臈l件查詢方式;Criteria的創(chuàng)建方式:

          Criteria crit = session.createCrieria(DomainClass.class);

          簡(jiǎn)單屬性條件如:

          criteria.add(Restrictions.eq(propertyName, value);

          criteria.add(Restrictions.eqProperty(propertyName, otherPropertyName));

              staticvoid cri(String name) {

                  Session s = null;

                  try {

                      s = HibernateUtil.getSession();

                      Criteria c = s.createCriteria(User.class);    //對(duì)User進(jìn)行約束查詢

                      c.add(Restrictions.eq("name", name)); //添加約束條件

                      c.add(Restrictions.lt("birthday", new Date()));

                      /**

                       * Criteria 查詢同樣提供了分頁

                       */

                      c.setFirstResult(200);

                      c.setMaxResults(210);

                      List<User> list = c.list();

                      for (User user : list) {

                          System.out.println(user.getName());

                      }

                  } finally {

                      if (s != null) {

                          s.close();

                      }

                  }

          }

          小貼士1、官方推薦HQL 查詢

          2、Hibernate try的異常可以不去操作,因?yàn)槭聞?wù)收不到commit事務(wù)就會(huì)回滾

          八、對(duì)象關(guān)系的關(guān)聯(lián)映射

          1.多對(duì)一(Employee - Department --- 最常用

          2.一對(duì)多(Department - Employee

          3.一對(duì)一(Person - IdCard

          4.多對(duì)多(Teacher - Student -- 需要建立中間表

          在操作和性能方面都不太理想,所以多對(duì)多的映射,實(shí)際使用中最好轉(zhuǎn)換成一對(duì)多的對(duì)象模型;Hibernate會(huì)為我們創(chuàng)建中間關(guān)聯(lián)表,轉(zhuǎn)換成兩個(gè)一對(duì)多。

          <set name="teacher" table="teacher_student">

          <key column="teacher_id"/>

          <many-to-many class="Student" column="student_id"/>

          </set>

          5.組件映射(User - Name

          關(guān)聯(lián)的屬性是個(gè)復(fù)雜類型的持久化類,但不是實(shí)體,即:數(shù)據(jù)庫中沒有表與該屬性對(duì)應(yīng),但該類的屬性要永久保存的。

          <component name="name" class="com.test.hibernate.domain.Name">

          <property name="initial" />

          <property name="first" />

          <property name="last" />

          </component>

          當(dāng)組件的屬性不能和表中的字段簡(jiǎn)單對(duì)應(yīng)的時(shí)候可以選擇實(shí)現(xiàn):

          org.hibernate.usertype.UserType or

          org.hibernate.usertype.CompositeUserType

          6.集合映射(setlistmapbag

          絕大部分使用set

          如果習(xí)慣使用list,又不想讓Hibernate維護(hù)順序,對(duì)象里用List,映射時(shí)用bag

          映射用listbag

          鍵值對(duì)方式用map

          數(shù)組因?yàn)閷?duì)元素變化應(yīng)用不方便

          <set name="employees">

          <key column="depart_id" />

          <one-to-many class="Employee" />

          <!-- <element type="string" column="name" /> -->

          <!--

          <composite-element class="YourClass">

          <property name="prop1" />

          <property name="prop2" />

          </composite>

          -->

          </set>

          7.InversecascadeEmployee - Department


          九、映射文件剖析

          1.hbm.cfg.xml

          a)       

          2.Xxx.hbm.xml

          a)       


          十、
          Hibernate的持久化操作

          1.save() //保存對(duì)象

          a)      把臨時(shí)對(duì)象加載到緩存中,使之成為持久化對(duì)象

          b)      使用指定的ID生成器為持久化對(duì)象分配OID

          c)      當(dāng)對(duì)象處于持久化狀態(tài)Hibernate不允許修改其IOD

          2.update() //修改對(duì)象

          a)      把游離對(duì)象加入到緩存中,使一個(gè)游離對(duì)象變成持久化對(duì)象

          b)      計(jì)劃執(zhí)行update SQL語句,根據(jù)對(duì)象IOD來更新對(duì)象所對(duì)應(yīng)的數(shù)據(jù)

          c)      Update不能更新一個(gè)在session中已經(jīng)關(guān)聯(lián)的相同OID的對(duì)象

          3.saveOrUpdate() //保存或修改對(duì)象

          a)      同時(shí)包含saveupdate方法的功能,根據(jù)對(duì)象的狀態(tài)自動(dòng)執(zhí)行相應(yīng)的功能

          b)      若對(duì)象為臨時(shí)狀態(tài)則執(zhí)行save,若為游離狀態(tài)則執(zhí)行update方法

          4.merge()//合并對(duì)象

          a)      直接修改表中的記錄,并不影響該對(duì)象原來的狀態(tài)

          5.delete()   //刪除指定的對(duì)象

          a)      如果是持久態(tài)對(duì)象,就計(jì)劃執(zhí)行delete語句

          b)      如果是游離狀態(tài)的對(duì)象,先使用游離對(duì)象被session緩存關(guān)聯(lián),變成持久化對(duì)象,再計(jì)劃執(zhí)行delete語句

          5.contains() //判斷實(shí)體對(duì)象是否與session關(guān)聯(lián)

          a)      可以用此方法判斷對(duì)象是否處于持久化狀態(tài)

          6.evict() //把實(shí)體對(duì)象從緩存中移除

          7.clear() //清除session緩存中所有持久化對(duì)象

          8.get/load 方法區(qū)別:

          a)      都是根據(jù)OID從數(shù)據(jù)庫中加載一個(gè)持久化對(duì)象

          b)      當(dāng)數(shù)據(jù)庫中不存在與OID對(duì)象的記錄時(shí),get()返回一個(gè)null引用,而load則會(huì)拋出ObjectNotFoundException異常

          c)      Load方法可以返回一個(gè)實(shí)體的代理類實(shí)例,而get方法只是直接返回實(shí)體類對(duì)象

          主站蜘蛛池模板: 教育| 从江县| 睢宁县| 鄱阳县| 南丰县| 林西县| 大荔县| 金湖县| 清新县| 庆城县| 上杭县| 松江区| 鹤峰县| 余江县| 东至县| 忻州市| 全椒县| 满洲里市| 舒城县| 昌吉市| 商洛市| 綦江县| 梨树县| 博乐市| 东明县| 盱眙县| 永平县| 营口市| 聂拉木县| 越西县| 邯郸县| 姚安县| 手游| 瑞昌市| 信阳市| 翼城县| 古田县| 红原县| 平塘县| 广南县| 理塘县|