hibernate 一級緩存:(緩存的是實體對象)

          一級緩存很短和session的生命周期一致,一級緩存也叫session級的緩存或事務(wù)緩存

           

          哪些方法支持一級緩存:

          *get()

          *load()

          *iterate()  (查詢實體對象)

           

          如何管理一級緩存:

          * session.clear() session.evict()

           

          如何避免一次性大量的實體數(shù)據(jù)入庫導(dǎo)致內(nèi)存溢出

          *先flush,再clear

           

          如果數(shù)據(jù)量特別大,考慮采用jdbc實現(xiàn),如果jdbc也不能滿足要求,可以考慮采用數(shù)據(jù)庫本身的特定導(dǎo)入工具

           

          一.Load測試: 在同一個session中發(fā)出兩次load查詢

                 Student sutdent = (Student)session.load(Student.class,1);

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

           

                 sutdent = (Student)session.load(Student.class,1);

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

                 在同一個session中發(fā)出兩次load查詢,第一次load的時候不會去查詢數(shù)據(jù)庫,因為他是LAZY的,當使用的時候才去查詢數(shù)據(jù)庫,  第二次load的時候也不會,當使用的時候也不會查詢數(shù)據(jù)庫,因為他在緩存里找到,不會發(fā)出sql

           

           

          Load測試: 開啟兩個session中發(fā)出兩次load查詢

          Student sutdent = (Student)session.load(Student.class,1);

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

          sessioin.close();

          ………..

                 sutdent = (Student)session.load(Student.class,1);

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

                 開啟兩個session中發(fā)出兩次load查詢,第一次load的時候不會去查詢數(shù)據(jù)庫,因為他是LAZY的,當使用的時候才去查詢數(shù)據(jù)庫,  第二次load的時候也不會,當使用的時候查詢數(shù)據(jù)庫,因為session間不能共享一級緩存的數(shù)據(jù),因為他會隨session的生命周期存在和消亡

           

           

          二.Get測試: 在同一個session中發(fā)出兩次get查詢

              Student sutdent = (Student)session.get(Student.class,1);

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

           

                 sutdent = (Student)session.get(Student.class,1);

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

                 在同一個session中發(fā)出兩次get查詢, 第一次get的時候去查詢數(shù)據(jù)庫,第二次get的時候不會查詢數(shù)據(jù)庫,因為他在緩存里找到,不會發(fā)出sql

           

           

          三.iterate測試: 在同一個session中發(fā)出兩次iterator查詢

          Student student = (Student)session.createQuery(“from Student s where s.id=1”).iterate().next();

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

           

          student = (Student)session.createQuery(“from Student s where s.id=1”).iterate().next();

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

                 在同一個session中發(fā)出兩次iterator查詢,第一次iterate().next()的時候會發(fā)出查詢id的sql,使用的時候會發(fā)出相應(yīng)的查詢實體對象,第二次iterate().next()的時候會發(fā)出查詢id的sql,不會發(fā)出查詢實體對象的sql,因為iterate使用緩存,不會發(fā)出sql

           

           

          四.Iterate查詢屬性測試: 同一個session中發(fā)出兩次查詢屬性

          String name = (String)session.createQuery(“select s.name from Student s where s.id=1”).iterate().next();

          System.out.println(name);

           

          String name = (String)session.createQuery(“select s.name from Student s where s.id=1”).iterate().next();

          System.out.println(name);

                 在同一個session中發(fā)出兩次查詢屬性, 第一次iterate().next()的時候會發(fā)出查詢屬性的sql,第二次iterate().next()的時候會發(fā)出查詢屬性的sql,iterate查詢普通屬性,一級緩存不會緩存,所以會發(fā)出sql

           

           

          五.同一個session中先save,再發(fā)出load查詢save過的數(shù)據(jù)

           

                 Student stu = new Student();

                 stu.setName(“王五”);

           

             Serializable id = session.save(stu);

           

          Student sutdent = (Student)session.load(Student.class,id);

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

           

                

          save的時候,他會在緩存里放一份,不會發(fā)出sql,因為save是使用緩存的

          六.同一個session中先調(diào)用load查詢,然后執(zhí)行sessio.clear()session.evict(),再調(diào)用load查詢

           

          Student sutdent = (Student)session.load(Student.class,1);

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

                 session.clear();

           

          Student sutdent = (Student)session.load(Student.class,1);

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

           

           

                 sessio.clear()或session.evict()可以管理一級緩存,一級緩存無法取消,但可以管理.

          上面的語句都會發(fā)出sql 因為一級緩存中的實體被清除了

           

          七.向數(shù)據(jù)庫中批量加入1000條數(shù)據(jù)

           

          for(int i=0;i<1000;i++){

                 Student student = new Student();

                 student.setName(“s” + i);

                 session.save(student);

          //每20條數(shù)據(jù)就強制session將數(shù)據(jù)持久化,同時清除緩存,避免大量數(shù)據(jù)造成內(nèi)存溢出

                 if( i %20 == 0 ){

                        session.flush();

                        session.clear();

          }

          }

           

          posted @ 2009-04-06 11:59 胡鵬 閱讀(416) | 評論 (0)編輯 收藏

           

          hibernate查詢緩存(hibernate默認是關(guān)閉的)

           

          查詢緩存是針對普通屬性結(jié)果集的緩存

          對實體對象的結(jié)果集只緩存id

           

          查詢緩存的生命周期,當前關(guān)聯(lián)的表發(fā)生修改,那么查詢緩存生命周期結(jié)束

           

          查詢緩存的配置和使用:

          1. 啟用查詢緩存:在hibernate.cfg.xml中加入:

          <property name=”hibernate.cache.use_query_cache”>true</property>

            2. 在程序中必須手動啟用查詢緩存,如:query.setCacheable(true);

           

           

          測試查詢緩存:

          一.  開啟查詢緩存,關(guān)閉二級緩存,開啟一個session,分別調(diào)用query.list  (查詢屬性)

           

          Query query = session.createQuery(“select s.name from Student s”);

          //啟用查詢緩存

          query.setCacheable(true);

           

          List names = query.list();

          for(Iterator iter = names.terator();iter.hasNext();){

                 String name = (String)iter.next();

                 System.out.println(name);

          }

           

          System.out.println(“------------------------------------------”);

           

          query = session.createQuery(“select s.name from Student s”);

          //啟用查詢緩存

          query.setCacheable(true);

           

          names = query.list();

          for(Iterator iter = names.terator();iter.hasNext();){

                 String name = (String)iter.next();

                 System.out.println(name);

          }

          第二次沒有去查詢數(shù)據(jù)庫,因為啟用了查詢緩存

           

          二.  開啟查詢緩存,關(guān)閉二級緩存,開啟兩個session,分別調(diào)用query.list  (查詢屬性)

           

          Query query = session.createQuery(“select s.name from Student s”);

          //啟用查詢緩存

          query.setCacheable(true);

           

          List names = query.list();

          for(Iterator iter = names.terator();iter.hasNext();){

                 String name = (String)iter.next();

                 System.out.println(name);

          }

           

          session.close();

           

          System.out.println(“------------------------------------------”);

          ………

          Query query = session.createQuery(“select s.name from Student s”);

          //啟用查詢緩存

          query.setCacheable(true);

           

          List names = query.list();

          for(Iterator iter = names.terator();iter.hasNext();){

                 String name = (String)iter.next();

                 System.out.println(name);

          }

          第二次沒有去查詢數(shù)據(jù)庫,因為查詢緩存生命周期與session生命周期無關(guān)

           

          三.  開啟查詢緩存,關(guān)閉二級緩存,開啟兩個session,分別調(diào)用query.iterate (查詢屬性)

           

          Query query = session.createQuery(“select s.name from Student s”);

          //啟用查詢緩存

          query.setCacheable(true);

           

          for(Iterator iter =query.iterate();iter.hasNext();){

                 String name = (String)iter.next();

                 System.out.println(name);

          }

           

          session.close();

           

          System.out.println(“------------------------------------------”);

          ………

          Query query = session.createQuery(“select s.name from Student s”);

          //啟用查詢緩存

          query.setCacheable(true);

           

          for(Iterator iter = query.iterate();iter.hasNext();){

                 String name = (String)iter.next();

                 System.out.println(name);

          }

          第二去查詢數(shù)據(jù)庫,因為查詢緩存只對query.list()起作用,對query.iterate()不起作用,也就是說query.iterate()不使用查詢緩存

           

          四.  關(guān)閉查詢緩存,關(guān)閉二級緩存,開啟兩個session,分別調(diào)用query.list (查詢實體對象)

           

          Query query = session.createQuery(“ from Student s”);

          //query.setCacheable(true);

          List students = query.list();

          for(Iterator iter = students.iterate();iter.hasNext();){

                 Student stu = (Student)iter.next();

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

          }

           

          session.close();

           

          System.out.println(“------------------------------------------”);

          ………

          Query query = session.createQuery(“ from Student s”);

          //query.setCacheable(true);

          List students = query.list();

          for(Iterator iter = students.iterate();iter.hasNext();){

                 Student stu = (Student)iter.next();

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

          }

          第二去查詢數(shù)據(jù)庫,因為list默認每次都會發(fā)出查詢sql

           

          五.  開啟查詢緩存,關(guān)閉二級緩存,開啟兩個session,分別調(diào)用query.list (查詢實體對象)

           

          Query query = session.createQuery(“ from Student s”);

          query.setCacheable(true);

          List students = query.list();

          for(Iterator iter = students.iterate();iter.hasNext();){

                 Student stu = (Student)iter.next();

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

          }

           

          session.close();

           

          System.out.println(“------------------------------------------”);

          ………

          Query query = session.createQuery(“ from Student s”);

          query.setCacheable(true);

          List students = query.list();

          for(Iterator iter = students.iterate();iter.hasNext();){

                 Student stu = (Student)iter.next();

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

          第二去查詢數(shù)據(jù)庫時,會發(fā)出N條sql語句,因為開啟了查詢緩存,關(guān)閉了二級緩存,那么查詢緩存會緩存實體對象的id,所以hibernate會根據(jù)實體對象的id去查詢相應(yīng)的實體,如果緩存中不存在相應(yīng)的實體,那么將發(fā)出根據(jù)實體id查詢的sql語句,否則不會發(fā)出sql,使用緩存中的數(shù)據(jù)

           

          六.  開啟查詢緩存,開啟二級緩存,開啟兩個session,分別調(diào)用query.list (查詢實體對象)

           

          Query query = session.createQuery(“ from Student s”);

          query.setCacheable(true);

          List students = query.list();

          for(Iterator iter = students.iterate();iter.hasNext();){

                 Student stu = (Student)iter.next();

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

          }

           

          session.close();

           

          System.out.println(“------------------------------------------”);

          ………

          Query query = session.createQuery(“ from Student s”);

          query.setCacheable(true);

          List students = query.list();

          for(Iterator iter = students.iterate();iter.hasNext();){

                 Student stu = (Student)iter.next();

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

          }

           

          第二不會發(fā)出sql,因為開啟了二級緩存和查詢緩存,查詢緩存緩存了實體對象的id列表,hibernate會根據(jù)實體對象的id列表到二級緩存中取得相應(yīng)的數(shù)據(jù)

          posted @ 2009-04-06 11:58 胡鵬 閱讀(4886) | 評論 (0)編輯 收藏

          悲觀鎖

                

                 悲觀鎖的實現(xiàn),通常依賴于數(shù)據(jù)庫機制,在整個過程中將數(shù)據(jù)鎖定,其它任何用戶都不能讀取或修改。

           

          舉個例子:

          //查詢id=1的那條記錄,使用悲觀鎖

          User user = (User)session.load(User.class, 1 ,  LockMode.UPGRADE);

          使用了數(shù)據(jù)庫中的 for update  鎖定

           

          樂觀鎖

          大多數(shù)基于數(shù)據(jù)版本記錄機制(version)實現(xiàn),一半是在數(shù)據(jù)庫表加入一個version字段,讀取數(shù)據(jù)時將版本號一同讀出,之后更新數(shù)據(jù)時版本號加一,如果提交數(shù)據(jù)時版本號小于或等于數(shù)據(jù)庫表中的版本號,則認為數(shù)據(jù)是過期的,否則給予更新。

           

          其實并非是鎖,是一種沖突檢測  (沒有hibernate也可以使用的,自己要在數(shù)據(jù)庫中建字段來控制,使用hibernate方便些,封裝好了)

           

          在*.hm.xml中 添加紅色部分:

                                                      

          <class

          name="com.tao3c.orm.TbBusinessInfo"  table="tb_business_info"  optimistic-lock=”version”>

           

          其中version是com.tao3c.orm.TbBusinessInfo類的屬性,hiernbate會去維護的,不用自己去該

           

           

          posted @ 2009-04-06 11:57 胡鵬 閱讀(230) | 評論 (0)編輯 收藏

          悲觀鎖

                

                 悲觀鎖的實現(xiàn),通常依賴于數(shù)據(jù)庫機制,在整個過程中將數(shù)據(jù)鎖定,其它任何用戶都不能讀取或修改。

           

          舉個例子:

          //查詢id=1的那條記錄,使用悲觀鎖

          User user = (User)session.load(User.class, 1 ,  LockMode.UPGRADE);

          使用了數(shù)據(jù)庫中的 for update  鎖定

           

          樂觀鎖

          大多數(shù)基于數(shù)據(jù)版本記錄機制(version)實現(xiàn),一半是在數(shù)據(jù)庫表加入一個version字段,讀取數(shù)據(jù)時將版本號一同讀出,之后更新數(shù)據(jù)時版本號加一,如果提交數(shù)據(jù)時版本號小于或等于數(shù)據(jù)庫表中的版本號,則認為數(shù)據(jù)是過期的,否則給予更新。

           

          其實并非是鎖,是一種沖突檢測  (沒有hibernate也可以使用的,自己要在數(shù)據(jù)庫中建字段來控制,使用hibernate方便些,封裝好了)

           

          在*.hm.xml中 添加紅色部分:

                                                      

          <class

          name="com.tao3c.orm.TbBusinessInfo"  table="tb_business_info"  optimistic-lock=”version”>

           

          其中version是com.tao3c.orm.TbBusinessInfo類的屬性,hiernbate會去維護的,不用自己去該

           

           

          posted @ 2009-04-06 11:57 胡鵬 閱讀(188) | 評論 (0)編輯 收藏

          hibernate中設(shè)置:

          查詢數(shù)據(jù)庫每次最多返回50條結(jié)果:

          <property name=”hibernate.jdbc.fetch_size”>50</property>

          30條更新數(shù)據(jù)庫一次:

          <property name= ”hibernatejdbc.batch_size”>30</property>

           但不是所有的數(shù)據(jù)庫都支持的,sqlServer orcale 都支持的。

           

          一.hibernate 抓取策略(Fetch) 單端代理批量抓取

           

          1.fetch=”select” 關(guān)聯(lián)實體

          //fetch 默認是select

          <many-to-one name="businessId" column="business_id" insert="true" update="true" fetch="select">

           

          Student student = (Student)session.load(Student.class,1);

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

          System.out.println(student.getClasses().getName()); //多對一中的屬性班級,獲取班級名稱

           

          Fetch=”select” ,上面程序會發(fā)2條sql語句,第二條發(fā)送一條select語句抓取當前對象關(guān)聯(lián)實體或集合 (這里指是班級名稱)

           

          2.fetch=” join” 關(guān)聯(lián)實體

          //fetch 設(shè)置成 join

          <many-to-one name="businessId" column="business_id" insert="true" update="true"

          fetch=" join ">

           

          Student student = (Student)session.load(Student.class,1);

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

          System.out.println(student.getClasses().getName()); //多對一中的屬性班級,獲取班級名稱

           

          fetch=” join” , 上面程序會發(fā)1條sql語句, hibernate會通過select使用外鏈接來加載其關(guān)聯(lián)實體或集合,此時lazy會失效 

           

          二.hibernate 抓取策略(Fetch) 集合代理批量抓取

           

          1.     fetch=”select”

          //fetch 默認是select

          <set name="students" inverse="true" cascade="all" fetch="select">

                      <key column="classid" />

                      <one-to-many class="com.Student" />

          </set>

           

          Classes cla = (Classes)session.load(Classes.class,1);

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

          for(Iterator iter = cla.getStudents().iterator();iter.hasNext();){

                 Student student = (Student)iter.next();

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

          }

           

          fetch=”select” ,上面程序用到了就發(fā)sql語句,第二從循環(huán)中發(fā)了N條,如果:fetch=”subselect”,則只是發(fā)送一條語句,見下面

           

          2 fetch=”join”

          //fetch 設(shè)置成join

          <set name="students" inverse="true" cascade="all" fetch="join">

                      <key column="classid" />

                      <one-to-many class="com.Student" />

          </set>

           

          Classes cla = (Classes)session.load(Classes.class,1);

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

          for(Iterator iter = cla.getStudents().iterator();iter.hasNext();){

                 Student student = (Student)iter.next();

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

          }

           

          Fetch=”select” ,上面程序只發(fā)了一條sql語句

           

           

          三.hibernate 抓取策略(Fetch) 集合代理批量抓取

           

          2.     fetch=”subselect”

          //fetch設(shè)置成subselect

          <set name="students" inverse="true" cascade="all" fetch="subselect">

                      <key column="classid" />

                      <one-to-many class="com.Student" />

          </set>

           

          List classesList = session.createQuery(“select c from Classes c where c.id in(1,2,3)”);

          for(Iterator iter=classesList.iterator();iter.hasNext();){

                 Classess classess = (Classess)iter.next();

                 System.out.println(“classes.name=”+ classes.getName());

                 for(Iterator iter1 = classess.getStudents().iterator();iter1.hasNext();){

                        Student student = (Student)iter1.next();

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

          }

          }

           

          Fetch=”subselct” ,另外發(fā)送一條select語句抓取在前面查詢到的所有實體對象的關(guān)聯(lián)集合

           

           

          四.hibernate 批量策略batch-size屬性,可以批量加載實體類,

          參見Classes.hbm.xml,同時集合也可以是使用,如:

           <set name="students" inverse="true" cascade="save-update" batch-size=”5”>

           

          在配置文件hbm.xml 設(shè)置中:

          <class name="com.Classes " table="tb_classes" batch-size=”3”>

           

          List students = session.createQuery(“select s from Student s where s.id in(:ids)”).setParameterList(“:ids”,new Object[]{1,11,21,31,41,51,61,71,81,91}).list();

           

          for(Iterator iter=students.iterator();iter.hasNext();){

                 Student student = (Sutdent)iter.next();

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

                 System.out.println(student.getClassess().getName());

           

          }

           

          當?shù)诙€for循環(huán)時,每次加載 之前設(shè)置的 數(shù)量 實體對象,  如:現(xiàn)在設(shè)置3,那么當Iterator iter=students.iterator();iter.hasNext();時候,他會查詢出3個student對象

          posted @ 2009-04-06 11:57 胡鵬 閱讀(463) | 評論 (0)編輯 收藏

          一.hibernate多對多映射(單項),自動產(chǎn)生第三張表

          User--à Role

          user(id,name)    role(id,name)

          User類:

          private int  id;   private String name;  private  Set roles;

           

          Role類:

          private int id;    private String name;

           

          User.hbm.xml中:

          <set name=”roles” table=”t_user_role”>

                 <key column=”userid” />

                 <many-to-many class=”com.Role” column=”roleid” />

          </set>

           

          這樣,hibernate會自動產(chǎn)生中間表t_user_role(userid,roleid) 并且是復(fù)合主鍵,userid為t_user的外鍵,roleid為t_role的外鍵

           

           

          二.hibernate多對多的存儲

           

          Role r1 = new Role();

          r1.setName(“數(shù)據(jù)錄入人員”);

           

          Role r2 = new Role();

          r2.setName(“商務(wù)主管”);

           

          Role r3 = new Role();

          r3.setName(“大區(qū)經(jīng)理”);

           

           

          User u1 = new User();

          u1.setName(“10”);

          Set u1Roles = new HashSet();

          u1Roles.add(r1);

          u1Roles.add(r2);

          u1.setRoles(u1Roles);

           

          User u2 = new User();

          u1.setName(“祖兒”);

          Set u2Roles = new HashSet();

          u2Roles.add(r2);

          u2Roles.add(r3);

          u2.setRoles(u2Roles);

          User u3 = new User();

          u3.setName(“杰倫”);

          Set u3Roles = new HashSet();

          u3Roles.add(r1);

          u3Roles.add(r2);

          u3Roles.add(r3);

          u3.setRoles(u3Roles);

           

           

          session.save(r1);

          session.save(r2);

          session.save(r3);

           

          session.save(u1);

          session.save(u2);

          session.save(u3);

           

          結(jié)束之后,在第三張表中也有數(shù)據(jù)

           

           

           

          三.hibernate多對多的加載

           

          User user = (User)session.load(User.class,1);

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

          for(Iterator iter = user.getRoles().iterator();iter.hasNext();){

                 Role role = (Role)iter.next();

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

           

          }

           每次加載都會發(fā)出sql語句

           

          三.hibernate多對多的 雙向映射

           

          User ß--.-àRole

          user(id,name)    role(id,name)

          User類:

          private int  id;   private String name;  private Set roles;

           

          Role類:

          private int id;    private String name; private Set users;

           

          User.hbm.xml中:

          <set name=”roles” table=”t_user_role”>

                 <key column=”userid” />

                 <many-to-many class=”com.Role” column=”roleid” />

          </set>

           

          Role.hbm.xml中:

          <set name=”roles” table=”t_user_role”>   //這里可以設(shè)置order-by=”userid”,根據(jù)userid排序

                 <key column=”roleid” />

                 <many-to-many class=”com.User” column=”userid” />

          </set>

           

          注意,上面中間表名字是一樣的

          這樣,hibernate也會自動產(chǎn)生中間表t_user_role(userid,roleid) 并且是復(fù)合主鍵,userid為t_user的外鍵,roleid為t_role的外鍵

           

          posted @ 2009-04-06 11:56 胡鵬 閱讀(1158) | 評論 (0)編輯 收藏

          一.hibernate多對多映射(單項),自動產(chǎn)生第三張表

          User--à Role

          user(id,name)    role(id,name)

          User類:

          private int  id;   private String name;  private  Set roles;

           

          Role類:

          private int id;    private String name;

           

          User.hbm.xml中:

          <set name=”roles” table=”t_user_role”>

                 <key column=”userid” />

                 <many-to-many class=”com.Role” column=”roleid” />

          </set>

           

          這樣,hibernate會自動產(chǎn)生中間表t_user_role(userid,roleid) 并且是復(fù)合主鍵,userid為t_user的外鍵,roleid為t_role的外鍵

           

           

          二.hibernate多對多的存儲

           

          Role r1 = new Role();

          r1.setName(“數(shù)據(jù)錄入人員”);

           

          Role r2 = new Role();

          r2.setName(“商務(wù)主管”);

           

          Role r3 = new Role();

          r3.setName(“大區(qū)經(jīng)理”);

           

           

          User u1 = new User();

          u1.setName(“10”);

          Set u1Roles = new HashSet();

          u1Roles.add(r1);

          u1Roles.add(r2);

          u1.setRoles(u1Roles);

           

          User u2 = new User();

          u1.setName(“祖兒”);

          Set u2Roles = new HashSet();

          u2Roles.add(r2);

          u2Roles.add(r3);

          u2.setRoles(u2Roles);

          User u3 = new User();

          u3.setName(“杰倫”);

          Set u3Roles = new HashSet();

          u3Roles.add(r1);

          u3Roles.add(r2);

          u3Roles.add(r3);

          u3.setRoles(u3Roles);

           

           

          session.save(r1);

          session.save(r2);

          session.save(r3);

           

          session.save(u1);

          session.save(u2);

          session.save(u3);

           

          結(jié)束之后,在第三張表中也有數(shù)據(jù)

           

           

           

          三.hibernate多對多的加載

           

          User user = (User)session.load(User.class,1);

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

          for(Iterator iter = user.getRoles().iterator();iter.hasNext();){

                 Role role = (Role)iter.next();

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

           

          }

           每次加載都會發(fā)出sql語句

           

          三.hibernate多對多的 雙向映射

           

          User ß--.-àRole

          user(id,name)    role(id,name)

          User類:

          private int  id;   private String name;  private Set roles;

           

          Role類:

          private int id;    private String name; private Set users;

           

          User.hbm.xml中:

          <set name=”roles” table=”t_user_role”>

                 <key column=”userid” />

                 <many-to-many class=”com.Role” column=”roleid” />

          </set>

           

          Role.hbm.xml中:

          <set name=”roles” table=”t_user_role”>   //這里可以設(shè)置order-by=”userid”,根據(jù)userid排序

                 <key column=”roleid” />

                 <many-to-many class=”com.User” column=”userid” />

          </set>

           

          注意,上面中間表名字是一樣的

          這樣,hibernate也會自動產(chǎn)生中間表t_user_role(userid,roleid) 并且是復(fù)合主鍵,userid為t_user的外鍵,roleid為t_role的外鍵

           

          posted @ 2009-04-06 11:56 胡鵬 閱讀(183) | 評論 (0)編輯 收藏

             

          單態(tài)定義:

          Singleton模式主要作用是保證在Java應(yīng)用程序中,一個類Class只有一個實例存在。

          在很多操作中,比如建立目錄 數(shù)據(jù)庫連接都需要這樣的單線程操作。

          還有, singleton能夠被狀態(tài)化; 這樣,多個單態(tài)類在一起就可以作為一個狀態(tài)倉庫一樣向外提供服務(wù),比如,你要論壇中的帖子計數(shù)器,每次瀏覽一次需要計數(shù),單態(tài)類能否保持住這個計數(shù),并且能synchronize的安全自動加1,如果你要把這個數(shù)字永久保存到數(shù)據(jù)庫,你可以在不修改單態(tài)接口的情況下方便的做到。

          另外方面,Singleton也能夠被無狀態(tài)化。提供工具性質(zhì)的功能,

          Singleton模式就為我們提供了這樣實現(xiàn)的可能。使用Singleton的好處還在于可以節(jié)省內(nèi)存,因為它限制了實例的個數(shù),有利于Java垃圾回收(garbage collection)。

          我們常常看到工廠模式中類裝入器(class loader)中也用Singleton模式實現(xiàn)的,因為被裝入的類實際也屬于資源。

          如何使用?

          一般Singleton模式通常有幾種形式:

          public class Singleton {

            private Singleton(){}

            //在自己內(nèi)部定義自己一個實例,是不是很奇怪?

            //注意這是private 只供內(nèi)部調(diào)用

            private static Singleton instance = new Singleton();

            //這里提供了一個供外部訪問本class的靜態(tài)方法,可以直接訪問  

            public static Singleton getInstance() {

              return instance;   

             }

          }

          第二種形式:

          public class Singleton {

            private static Singleton instance = null;

            public static synchronized Singleton getInstance() {

            //這個方法比上面有所改進,不用每次都進行生成對象,只是第一次     

            //使用時生成實例,提高了效率!

            if (instance==null)

              instance=new Singleton();

            return instance;   }

          }

          使用Singleton.getInstance()可以訪問單態(tài)類。

          上面第二中形式是lazy initialization,也就是說第一次調(diào)用時初始Singleton,以后就不用再生成了。

          注意到lazy initialization形式中的synchronized,這個synchronized很重要,如果沒有synchronized,那么使用getInstance()是有可能得到多個Singleton實例。關(guān)于lazy initialization的Singleton有很多涉及double-checked locking (DCL)的討論,有興趣者進一步研究。

          一般認為第一種形式要更加安全些。

          使用Singleton注意事項:

          有時在某些情況下,使用Singleton并不能達到Singleton的目的,如有多個Singleton對象同時被不同的類裝入器裝載;在EJB這樣的分布式系統(tǒng)中使用也要注意這種情況,因為EJB是跨服務(wù)器,跨JVM的。

          我們以SUN公司的寵物店源碼(Pet Store 1.3.1)的ServiceLocator為例稍微分析一下:

          在Pet Store中ServiceLocator有兩種,一個是EJB目錄下;一個是WEB目錄下,我們檢查這兩個ServiceLocator會發(fā)現(xiàn)內(nèi)容差不多,都是提供EJB的查詢定位服務(wù),可是為什么要分開呢?仔細研究對這兩種ServiceLocator才發(fā)現(xiàn)區(qū)別:在WEB中的ServiceLocator的采取Singleton模式,ServiceLocator屬于資源定位,理所當然應(yīng)該使用Singleton模式。但是在EJB中,Singleton模式已經(jīng)失去作用,所以ServiceLocator才分成兩種,一種面向WEB服務(wù)的,一種是面向EJB服務(wù)的。

          Singleton模式看起來簡單,使用方法也很方便,但是真正用好,是非常不容易,需要對Java的類 線程內(nèi)存等概念有相當?shù)牧私狻?/p>

          總之:如果你的應(yīng)用基于容器,那么Singleton模式少用或者不用,可以使用相關(guān)替代技術(shù)。

          posted @ 2009-04-06 11:55 胡鵬 閱讀(325) | 評論 (0)編輯 收藏
            
             

          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() 強制數(shù)據(jù)庫立即同步,當用事務(wù)時,不必用flush,事務(wù)提交自動調(diào)用flush在session關(guān)閉時也會調(diào)用flush

           

          4. Hibernate總是使用對象類型作為字段類型

           

          5. XDoclet專門建立了hibernate doclet,就是在java代碼上加上一些java docTag,后來再讓XDoclet分析該java代碼,生成映射文件;

           

          6.HQL子句本身大小寫無關(guān),但是其中出現(xiàn)的類名和屬性名必須注意大小寫區(qū)分。

           

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

           

          property-ref:關(guān)聯(lián)類中用于與主控類相關(guān)聯(lián)的屬性名,默認為關(guān)聯(lián)類的主鍵屬性名

           

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

           

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

           

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

           

          10.重要:inverse:用于標識雙向關(guān)聯(lián)中的被動方一端。

           

          inverse=false的一方(主控方)負責維護關(guān)聯(lián)關(guān)系.默認值:false

           

          11.batch-size:采用延遲加載特征時,一次讀入的數(shù)據(jù)數(shù)昨。

           

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

           

          user.getAddresses().add(addr);

           

          session.save(user);//通過主控對象級聯(lián)更新

           

          13.在one-to-many 關(guān)系中,將many 一方設(shè)為主動方(inverse=false)將有助性能的改善。在一方設(shè)置關(guān)系時,inverse=true,即將主控權(quán)交給多方, 這樣多方可主動從一方獲得foreign key,然后一次insert即可完工。

           

          addr.setUser(user);//設(shè)置關(guān)聯(lián)的TUser對象

           

          user.getAddresses().add(addr);

           

          session.save(user);//級聯(lián)更新

           

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

           

          15.one-to-many與many-to-one節(jié)點的配置屬性不同:

           

          一對多關(guān)系多了lazy和inverse兩個屬性多對多節(jié)點屬性:

           

          column:中間映射表中,關(guān)聯(lián)目標表的關(guān)聯(lián)字段

           

          class:類名,關(guān)聯(lián)目標類

           

          outer-join:是否使用外聯(lián)接

           

          注意:access是設(shè)置屬性值的讀取方式。

           

          column是設(shè)置關(guān)聯(lián)字段。

           

          16.多對多,注意兩方都要設(shè)置inverse和lazy,cascade只能設(shè)為insert-update

           

          多對多關(guān)系中,由于關(guān)聯(lián)關(guān)系是兩張表相互引用,因此在保存關(guān)系狀態(tài)時必須對雙方同時保存。

           

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

           

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

           

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

           

          18.對于save操作而言,如果對象已經(jīng)與Session相關(guān)聯(lián)(即已經(jīng)被加入Session的實體容器中),則無需進行具體的操作。因為之后的Session.flush過程中,Hibernate 會對此實體容器中的對象進行遍歷,查找出發(fā)生變化的實體,生成并執(zhí)行相應(yīng)的update 語句。

           

          19.如果我們采用了延遲加載機制,但希望在一些情況下,實現(xiàn)非延遲加載時的功能,也就是說,我們希望在Session關(guān)閉后,依然允許操作user的addresses 屬性 Hibernate.initialize方法可以通過強制加載關(guān)聯(lián)對象實現(xiàn)這一功能: 這也正是我們?yōu)槭裁丛诰帉慞OJO時,必須用JDK Collection接口(如Set,Map), 而非特定的JDK Collection實現(xiàn)類(如HashSet、HashMap)申明Collection屬性的 原因。

           

          20.事務(wù):從sessionFactory獲得session,其自動提交屬性就已經(jīng)關(guān)閉(AutoCommit=false),此時若執(zhí)行了jdbc操作,如果不顯式調(diào)用session.BeginTransaction(),是不會執(zhí)行事務(wù)操作的。

           

          jdbc transaction:基于同一個session(就是同一個connection)的事務(wù);

           

          jta transaction:跨session(跨connection)事務(wù).

           

          對于jta事務(wù),有三種實現(xiàn)方法:

           

          A。UserTransaction tx=new InitialContext().lookup("...");

          tx.commit();

           

          B. 使用hibernate封裝的方法:(不推薦)

           

          Transaction tx=session.beginTransaction();

          tx.commit();

          C. 使用ejb之sessionBean的事務(wù)技持方法,你只要在把需要在發(fā)布描述符中,把需要jta事務(wù)的方法聲明為require即可

           

          21.悲觀鎖,樂觀鎖: 樂觀鎖一般通過version來實現(xiàn),注意version節(jié)點必須出現(xiàn)在id后。

           

          22.Hibernate中,可以通過Criteria.setFirstResult和Criteria.setFetchSize方法設(shè)定分頁范圍。

           

          Query接口中也提供了與其一致的方法,hibernate主要在dialect類中實現(xiàn)在這個功能。

           

          23.cache

           

          ……

           

          net.sf.ehcache.hibernate.Provider 

           

          還需對ecache本身進配置

           

           

           

          之后在映射文件中指定各個映射實體的cache策略

           

           

          ....

           

           

          ....

           

           

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

           

          也就是說,對于list 操作,需要一條SQL 完成。而對于iterate 操作,需要n+1 條SQL。,list方法將不會從Cache中讀取數(shù)據(jù)。iterator卻會。

           

          24.ThreadLocal:它會為每個線程維護一個私有的變量空間。實際上, 其實現(xiàn)原理是在JVM 中維護一個Map,這個Map的key 就是當前的線程對象,而value則是線程通過ThreadLocal.set方法保存的對象實例。當線程調(diào)用ThreadLocal.get方法時, ThreadLocal會根據(jù)當前線程對象的引用,取出Map中對應(yīng)的對象返回。

           

          這樣,ThreadLocal通過以各個線程對象的引用作為區(qū)分,從而將不同線程的變量隔離開來。

           

          25.Hibernate官方開發(fā)手冊標準示例:

           

          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實現(xiàn)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);

          } } } } ……}

          posted @ 2009-04-06 11:53 胡鵬 閱讀(214) | 評論 (0)編輯 收藏
          Eclipse快捷鍵指南   

          有些還是比叫有用的,不過不是很全


          編輯
          作用域 功能 快捷鍵
          全局 查找并替換 Ctrl+F
          文本編輯器 查找上一個 Ctrl+Shift+K
          文本編輯器 查找下一個 Ctrl+K
          全局 撤銷 Ctrl+Z
          全局 復(fù)制 Ctrl+C
          全局 恢復(fù)上一個選擇 Alt+Shift+↓
          全局 剪切 Ctrl+X
          全局 快速修正 Ctrl1+1
          全局 內(nèi)容輔助 Alt+/
          全局 全部選中 Ctrl+A
          全局 刪除 Delete
          全局 上下文信息 Alt+?
          Alt+Shift+?
          Ctrl+Shift+Space
          Java編輯器 顯示工具提示描述 F2
          Java編輯器 選擇封裝元素 Alt+Shift+↑
          Java編輯器 選擇上一個元素 Alt+Shift+←
          Java編輯器 選擇下一個元素 Alt+Shift+→
          文本編輯器 增量查找 Ctrl+J
          文本編輯器 增量逆向查找 Ctrl+Shift+J
          全局 粘貼 Ctrl+V
          全局 重做 Ctrl+Y

          查看
          作用域 功能 快捷鍵
          全局 放大 Ctrl+=
          全局 縮小 Ctrl+-


          窗口
          作用域 功能 快捷鍵
          全局 激活編輯器 F12
          全局 切換編輯器 Ctrl+Shift+W
          全局 上一個編輯器 Ctrl+Shift+F6
          全局 上一個視圖 Ctrl+Shift+F7
          全局 上一個透視圖 Ctrl+Shift+F8
          全局 下一個編輯器 Ctrl+F6
          全局 下一個視圖 Ctrl+F7
          全局 下一個透視圖 Ctrl+F8
          文本編輯器 顯示標尺上下文菜單 Ctrl+W
          全局 顯示視圖菜單 Ctrl+F10
          全局 顯示系統(tǒng)菜單 Alt+-


          導(dǎo)航
          作用域 功能 快捷鍵
          Java編輯器 打開結(jié)構(gòu) Ctrl+F3
          全局 打開類型 Ctrl+Shift+T
          全局 打開類型層次結(jié)構(gòu) F4
          全局 打開聲明 F3
          全局 打開外部javadoc Shift+F2
          全局 打開資源 Ctrl+Shift+R
          全局 后退歷史記錄 Alt+←
          全局 前進歷史記錄 Alt+→
          全局 上一個 Ctrl+,
          全局 下一個 Ctrl+.
          Java編輯器 顯示大綱 Ctrl+O
          全局 在層次結(jié)構(gòu)中打開類型 Ctrl+Shift+H
          全局 轉(zhuǎn)至匹配的括號 Ctrl+Shift+P
          全局 轉(zhuǎn)至上一個編輯位置 Ctrl+Q
          Java編輯器 轉(zhuǎn)至上一個成員 Ctrl+Shift+↑
          Java編輯器 轉(zhuǎn)至下一個成員 Ctrl+Shift+↓
          文本編輯器 轉(zhuǎn)至行 Ctrl+L


          搜索
          作用域 功能 快捷鍵
          全局 出現(xiàn)在文件中 Ctrl+Shift+U
          全局 打開搜索對話框 Ctrl+H
          全局 工作區(qū)中的聲明 Ctrl+G
          全局 工作區(qū)中的引用 Ctrl+Shift+G


          文本編輯
          作用域 功能 快捷鍵
          文本編輯器 改寫切換 Insert
          文本編輯器 上滾行 Ctrl+↑
          文本編輯器 下滾行 Ctrl+↓


          文件
          作用域 功能 快捷鍵
          全局 保存 Ctrl+X
          Ctrl+S

          posted @ 2009-04-06 11:46 胡鵬 閱讀(275) | 評論 (0)編輯 收藏
          僅列出標題
          共10頁: First 上一頁 2 3 4 5 6 7 8 9 10 下一頁 

          導(dǎo)航

          <2025年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          統(tǒng)計

          常用鏈接

          留言簿(3)

          隨筆分類

          隨筆檔案

          agile

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 西畴县| 鄱阳县| 喀喇沁旗| 方山县| 西盟| 临安市| 延长县| 辽源市| 大余县| 舒城县| 龙州县| 当阳市| 鄱阳县| 上虞市| 湖口县| 哈巴河县| 泾川县| 宜君县| 奉贤区| 洱源县| 兴隆县| 潮安县| 新营市| 广宁县| 高邑县| 安徽省| 泸溪县| 文水县| 五台县| 东乡县| 治多县| 滦南县| 昌江| 文水县| 准格尔旗| 阿鲁科尔沁旗| 墨江| 丰都县| 兴仁县| 永顺县| 通山县|