歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Hibernate 查詢1+N問題詳解

1、1+N簡單來說就是,Person和Phone是一對多關系,現在我看看所有手機的信息,對於其屬於哪個人不感興趣,但把lazy設為false(lazy=false),這樣就會發出1(查詢手機的sql)+N(和所有查詢的這些手機相關的Person的查詢sql),這樣會造成很大的性能開銷。

首先列一下會產生1+N問題的代碼

Person:

[java]
  1. private int id;  
  2. private String name;  
  3. private int age;  
Person.hbm.xml按照常規配置即可

Phone:

[java]
  1. private int id;  
  2. private String type;  
  3. private String description;  
  4. private Person person;  //關聯一個用戶  
Phone.hbm.xml:

[html]
  1. <hibernate-mapping>  
  2.     <class name="com.akwolf.n_1.Phone" table="PHONE">  
  3.         <id name="id" type="int">  
  4.             <column name="ID" />  
  5.             <generator class="native" />  
  6.         </id>  
  7.         <property name="type" type="java.lang.String">  
  8.             <column name="TYPE" />  
  9.         </property>  
  10.         <property name="description" type="java.lang.String">  
  11.             <column name="DESCRIPTION" />  
  12.         </property>  
  13.         <!-- lazy=false -->  
  14.         <many-to-one name="person" class="com.akwolf.n_1.Person" fetch="join" lazy="false">  
  15.             <column name="PERSON_ID" />  
  16.         </many-to-one>  
  17.     </class>  
  18. </hibernate-mapping>  

為了使效果明顯一點,假定一個手機對應一個不同的用戶,現在想數據庫中添加一些數據:

[java]

  1. @Test  
  2. public void testSave1() {  
  3.     Session session = HibernateUtil.getSessionFactory().getCurrentSession();  
  4.     session.beginTransaction();  
  5.     Person person;  
  6.     Phone phone;  
  7.   
  8.     for (int i = 0; i < 10; i++) {  
  9.         person = new Person(0"zhangsan" + i, 21 + i);  
  10.   
  11.         phone = new Phone(0"glay" + i, "Android智能手機", person);  
  12.         session.save(person);  
  13.         session.save(phone);  
  14.     }  
  15.     session.getTransaction().commit();  
  16. }  

進行一下下面的查詢會看到,控制台輸出大量的sql

[java]
  1. @Test  
  2. public void testQuery1() {  
  3.     Session session = HibernateUtil.getSessionFactory().getCurrentSession();  
  4.     session.beginTransaction();  
  5.     List<Phone> list = (List<Phone>) session.createQuery("from Phone")  
  6.             .list();  
  7.     for (Phone phone : list) {  
  8.         System.out.println(phone.getId()); //對關聯的Person並不感興趣   
  9.         // System.out.println(phone.getId()+"---"+phone.getPerson().getName());   
  10.     }  
  11.     session.getTransaction().commit();  
  12. }  

解決方案

1、還是在Phone.hbm.xml中把對於Person關聯的映射屬性不進行lazy屬性的設置,默認為lazy加載

[html]
  1. <hibernate-mapping>  
  2.     <class name="com.akwolf.n_1.Phone" table="PHONE">  
  3.         <id name="id" type="int">  
  4.             <column name="ID" />  
  5.             <generator class="native" />  
  6.         </id>  
  7.         <property name="type" type="java.lang.String">  
  8.             <column name="TYPE" />  
  9.         </property>  
  10.         <property name="description" type="java.lang.String">  
  11.             <column name="DESCRIPTION" />  
  12.         </property>  
  13.         <!-- lazy=true -->  
  14.         <many-to-one name="person" class="com.akwolf.n_1.Person" fetch="join">  
  15.             <column name="PERSON_ID" />  
  16.         </many-to-one>  
  17.     </class>  
  18. </hibernate-mapping>  
2、在lazy=false的情況下,在hql中使用join fetch進行查詢(session.createCriteria就是采用連接查詢的方式),如:

[java]
  1. @Test  
  2. public void testQuery2() {  
  3.     Session session = HibernateUtil.getSessionFactory().getCurrentSession();  
  4.     session.beginTransaction();  
  5.     List<Phone> list = (List<Phone>) session.createQuery(  
  6.             "from Phone p left join fetch p.person per").list();  
  7.     for (Phone phone : list) {  
  8.         // System.out.println(phone.getId());   
  9.         System.out.println(phone.getId() + "---"  
  10.                 + phone.getPerson().getName());  
  11.     }  
  12.     session.getTransaction().commit();  
  13. }  
3、對於在Person中設置batch-size應該不算是一種解決方案,對於海量的數據,設置的一些batch-size對於大體來說是無關痛癢的。

ok,這就是小弟看視頻對於1+N問題的一點理解,有理解更為深刻的大蝦不吝賜教。。

Copyright © Linux教程網 All Rights Reserved