1、1+N簡單來說就是,Person和Phone是一對多關系,現在我看看所有手機的信息,對於其屬於哪個人不感興趣,但把lazy設為false(lazy=false),這樣就會發出1(查詢手機的sql)+N(和所有查詢的這些手機相關的Person的查詢sql),這樣會造成很大的性能開銷。
首先列一下會產生1+N問題的代碼
Person:
[java]
- private int id;
- private String name;
- private int age;
Person.hbm.xml按照常規配置即可
Phone:
[java]
- private int id;
- private String type;
- private String description;
- private Person person; //關聯一個用戶
Phone.hbm.xml:
[html]
- <hibernate-mapping>
- <class name="com.akwolf.n_1.Phone" table="PHONE">
- <id name="id" type="int">
- <column name="ID" />
- <generator class="native" />
- </id>
- <property name="type" type="java.lang.String">
- <column name="TYPE" />
- </property>
- <property name="description" type="java.lang.String">
- <column name="DESCRIPTION" />
- </property>
- <!-- lazy=false -->
- <many-to-one name="person" class="com.akwolf.n_1.Person" fetch="join" lazy="false">
- <column name="PERSON_ID" />
- </many-to-one>
- </class>
- </hibernate-mapping>
為了使效果明顯一點,假定一個手機對應一個不同的用戶,現在想數據庫中添加一些數據:
[java]
- @Test
- public void testSave1() {
- Session session = HibernateUtil.getSessionFactory().getCurrentSession();
- session.beginTransaction();
- Person person;
- Phone phone;
-
- for (int i = 0; i < 10; i++) {
- person = new Person(0, "zhangsan" + i, 21 + i);
-
- phone = new Phone(0, "glay" + i, "Android智能手機", person);
- session.save(person);
- session.save(phone);
- }
- session.getTransaction().commit();
- }
進行一下下面的查詢會看到,控制台輸出大量的sql
[java]
- @Test
- public void testQuery1() {
- Session session = HibernateUtil.getSessionFactory().getCurrentSession();
- session.beginTransaction();
- List<Phone> list = (List<Phone>) session.createQuery("from Phone")
- .list();
- for (Phone phone : list) {
- System.out.println(phone.getId()); //對關聯的Person並不感興趣
- // System.out.println(phone.getId()+"---"+phone.getPerson().getName());
- }
- session.getTransaction().commit();
- }
解決方案
1、還是在Phone.hbm.xml中把對於Person關聯的映射屬性不進行lazy屬性的設置,默認為lazy加載
[html]
- <hibernate-mapping>
- <class name="com.akwolf.n_1.Phone" table="PHONE">
- <id name="id" type="int">
- <column name="ID" />
- <generator class="native" />
- </id>
- <property name="type" type="java.lang.String">
- <column name="TYPE" />
- </property>
- <property name="description" type="java.lang.String">
- <column name="DESCRIPTION" />
- </property>
- <!-- lazy=true -->
- <many-to-one name="person" class="com.akwolf.n_1.Person" fetch="join">
- <column name="PERSON_ID" />
- </many-to-one>
- </class>
- </hibernate-mapping>
2、在lazy=false的情況下,在hql中使用join fetch進行查詢(session.createCriteria就是采用連接查詢的方式),如:
[java]
- @Test
- public void testQuery2() {
- Session session = HibernateUtil.getSessionFactory().getCurrentSession();
- session.beginTransaction();
- List<Phone> list = (List<Phone>) session.createQuery(
- "from Phone p left join fetch p.person per").list();
- for (Phone phone : list) {
- // System.out.println(phone.getId());
- System.out.println(phone.getId() + "---"
- + phone.getPerson().getName());
- }
- session.getTransaction().commit();
- }
3、對於在Person中設置batch-size應該不算是一種解決方案,對於海量的數據,設置的一些batch-size對於大體來說是無關痛癢的。
ok,這就是小弟看視頻對於1+N問題的一點理解,有理解更為深刻的大蝦不吝賜教。。