码迷,mamicode.com
首页 > Web开发 > 详细

Hibernate的1+N问题

时间:2015-09-03 23:08:05      阅读:180      评论:0      收藏:0      [点我收藏+]

标签:

Hibernate 1+N

1+N问题的描述:举例,一个帖子(Category)含有多个主题(Topic)多个主题(Topic)属于一个帖子(Category),当只需要查询Topic时不要查询Category时,如果 @ManyToOne的属性fetch=FetchType.EAGER,这时查询所有Topic时,每查询一个Topic就会多产生一个SQL语句查询 相关的Category表的数据,这样要是有N条Topic数据,就会产生1+N条SQL语句。同样的在@OneToMany的情况下,要是在Many方 设置fetch=FetchType.EAGER,同样也会产生1+N的问题。

 

解决方案有三种:

1. fetch=FetchType.LAZY,设为懒加载

2. @BatchSize(size=5)代表一次取5条数据,这样取5条数据只要发出一条SQL语句,注意是用在被关联类上的(不建议用)

3. 迫切左外连接检索 join fetch(Criteria 查询默认就是join fetch

Category类

 1 package com.lbx.model;
 2 
 3 import javax.persistence.Entity;
 4 import javax.persistence.GeneratedValue;
 5 import javax.persistence.Id;
 6 
 7 import org.hibernate.annotations.BatchSize;
 8 
 9 @Entity
10 @BatchSize(size=2)
11 public class Category {
12     
13     private int id;
14     private String name;
15     
16     @Id
17     @GeneratedValue
18     public int getId() {
19         return id;
20     }
21     public void setId(int id) {
22         this.id = id;
23     }
24     public String getName() {
25         return name;
26     }
27     public void setName(String name) {
28         this.name = name;
29     }
30     
31 }

Topic类

 1 package com.lbx.model;
 2 
 3 import javax.persistence.Entity;
 4 import javax.persistence.FetchType;
 5 import javax.persistence.GeneratedValue;
 6 import javax.persistence.Id;
 7 import javax.persistence.ManyToOne;
 8 
 9 @Entity
10 public class Topic {
11 
12     private int id;
13     private String title;
14     private Category category;
15     
16     @Id
17     @GeneratedValue
18     public int getId() {
19         return id;
20     }
21     public void setId(int id) {
22         this.id = id;
23     }
24     public String getTitle() {
25         return title;
26     }
27     public void setTitle(String title) {
28         this.title = title;
29     }
30     
31     //@ManyToOne(fetch=FetchType.LAZY)
32     @ManyToOne
33     public Category getCategory() {
34         return category;
35     }
36     public void setCategory(Category category) {
37         this.category = category;
38     }
39     
40 }

hibernate.cfg.xml文件配置

 1 <?xml version=‘1.0‘ encoding=‘utf-8‘?>
 2 <!DOCTYPE hibernate-configuration PUBLIC
 3         "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 4         "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
 5 
 6 <hibernate-configuration>
 7 
 8     <session-factory>
 9 
10         <!-- Database connection settings -->
11         <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
12         <property name="connection.url">jdbc:mysql://localhost:3306/testhib</property>
13         <property name="connection.username">root</property>
14         <property name="connection.password">root</property>
15 
16         <!-- JDBC connection pool (use the built-in) -->
17        <!-- <property name="connection.pool_size">1</property> --> 
18 
19         <!-- SQL dialect -->
20         <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
21 
22         <!-- Enable Hibernate‘s automatic session context management -->
23         <!-- <property name="current_session_context_class">thread</property>  -->
24 
25         <!-- Echo all executed SQL to stdout -->
26         <property name="show_sql">true</property>
27         <property name="hibernate.format_sql">true</property>
28 
29         <!-- Drop and re-create the database schema on startup -->
30         <property name="hbm2ddl.auto">update</property>
31 
32         <mapping class="com.lbx.model.Category"/>
33         <mapping class="com.lbx.model.Topic"/>
34         <mapping class="com.lbx.model.Msg"/>
35     </session-factory>
36 
37 </hibernate-configuration>

测试代码

  1 package com.lbx.model.test;
  2 
  3 import java.util.List;
  4 
  5 import javax.persistence.FetchType;
  6 import javax.persistence.ManyToOne;
  7 
  8 import junit.framework.TestCase;
  9 
 10 import org.hibernate.Query;
 11 import org.hibernate.Session;
 12 import org.hibernate.lucene.Text;
 13 
 14 import com.lbx.hibernate.Util.HibUtil;
 15 import com.lbx.model.Category;
 16 import com.lbx.model.Msg;
 17 import com.lbx.model.Topic;
 18 
 19 public class Test extends TestCase {
 20     
 21     @Text
 22     public void save(){
 23         Session session = HibUtil.getSession();
 24         session.beginTransaction();
 25         
 26         for (int i = 0; i < 3; i++) {
 27             Category c = new Category();
 28             c.setName("c" + i);
 29             Topic t = new Topic();
 30             t.setTitle("t" + i);
 31             t.setCategory(c);
 32             session.save(c);
 33             session.save(t);
 34         }
 35         
 36         session.beginTransaction().commit();
 37         session.close();
 38     }
 39     
 40     //1+N问题(这里我只要取出Topic就可以了)
 41     @Text
 42     public void testHQL_01(){
 43         Session session = HibUtil.getSession();
 44         session.beginTransaction();
 45         
 46         //List<Topic> topics = (List<Topic>)session.createCriteria(Topic.class).list();
 47         /**
 48          * 这里要是不把Topic类中不设 @ManyToOne(fetch=FetchType.LAZY),这里就要发很多SQL语句,关联的表都会查
 49          * 但是设了@ManyToOne(fetch=FetchType.LAZY) 之后就不会发出查询相关表的查询语句,用到的时候才发出
 50          */
 51         Query q = session.createQuery("from Topic");
 52         List<Topic> topics = (List<Topic>)q.list();
 53         System.out.println(topics.size());
 54         for (int i = 0; i < topics.size(); i++) {
 55             System.out.println(topics.get(i).getId() + "  " + topics.get(i).getTitle());
 56         }
 57         session.beginTransaction().commit();
 58         session.close();
 59     }
 60     
 61     //用到被关联表的信息
 62     @Text
 63     public void testHQL_02(){
 64         Session session = HibUtil.getSession();
 65         session.beginTransaction();
 66         
 67         //List<Topic> topics = (List<Topic>)session.createCriteria(Topic.class).list();
 68         /**
 69          * 这里要是不把Topic类中不设 @ManyToOne(fetch=FetchType.LAZY),这里就要发很多SQL语句,关联的表都会查
 70          * 但是设了@ManyToOne(fetch=FetchType.LAZY) 之后就不会发出查询相关表的查询语句,用到的时候才发出
 71          */
 72         Query q = session.createQuery("from Topic");
 73         List<Topic> topics = (List<Topic>)q.list();
 74         System.out.println(topics.size());
 75         for (int i = 0; i < topics.size(); i++) {
 76             System.out.println(topics.get(i).getId() + "  " + topics.get(i).getTitle());
 77             /**
 78              * 注意,在这里要用到Category类的信息,所以就会发出相关的查询信息
 79              */
 80             System.out.println(topics.get(i).getCategory().getId() + "  " + 
 81                     topics.get(i).getCategory().getName());
 82         }
 83         session.beginTransaction().commit();
 84         session.close();
 85     }
 86     
 87     //@BatchSize的使用,其属性size=5就代表一次取5个
 88     @Text
 89     public void testHQL_03(){
 90         Session session = HibUtil.getSession();
 91         session.beginTransaction();
 92         
 93         //List<Topic> topics = (List<Topic>)session.createCriteria(Topic.class).list();
 94         /**
 95          * 这里要是不把Topic类中不设 @ManyToOne(fetch=FetchType.LAZY),这里就要发很多SQL语句,关联的表都会查
 96          * 但是设了@ManyToOne(fetch=FetchType.LAZY) 之后就不会发出查询相关表的查询语句,用到的时候才发出
 97          */
 98         Query q = session.createQuery("from Topic");
 99         List<Topic> topics = (List<Topic>)q.list();
100         System.out.println(topics.size());
101         for (int i = 0; i < topics.size(); i++) {
102             System.out.println(topics.get(i).getId() + "  " + topics.get(i).getTitle());
103             /**
104              * 注意,在这里要用到Category类的信息,所以就会发出相关的查询信息
105              */
106             System.out.println(topics.get(i).getCategory().getId() + "  " + 
107                     topics.get(i).getCategory().getName());
108         }
109         session.beginTransaction().commit();
110         session.close();
111     }
112     
113     // join fetch,迫切左外连接检索
114     @Text
115     public void testHQL_04(){
116         Session session = HibUtil.getSession();
117         session.beginTransaction();
118         //Criteria 查询默认就是join fetch
119         //List<Topic> topics = (List<Topic>)session.createCriteria(Topic.class).list();  
120         /**
121          * 这里要是不把Topic类中不设 @ManyToOne(fetch=FetchType.LAZY),这里就要发很多SQL语句,关联的表都会查
122          * 但是设了@ManyToOne(fetch=FetchType.LAZY) 之后就不会发出查询相关表的查询语句,用到的时候才发出
123          */
124         Query q = session.createQuery("from Topic t left join fetch t.category c");
125         List<Topic> topics = (List<Topic>)q.list();
126         System.out.println(topics.size());
127         for (int i = 0; i < topics.size(); i++) {
128             System.out.println(topics.get(i).getId() + "  " + topics.get(i).getTitle());
129         }
130         session.beginTransaction().commit();
131         session.close();
132     }
133     
134 }

 

Hibernate的1+N问题

标签:

原文地址:http://www.cnblogs.com/angleBlue/p/4780793.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!