标签:
session级缓存 保存一个hashmap, 读出来的对象放在里面, 如果读出来50条放50条, 如果另起session原来的50条就被清除.可以手动session.clear清除.
如果同一个session里一直读, 内存里越来越多. 所以要用session.clear()处理.
java有内存泄露吗? 语法上来说没有, 但是写程序的时候会有, 用了资源要回收, 比如打开连接池.
1+N问题: 如果一个对象里关联另外一个对象, 同时fetchtype为eager, 比如many to one, 要取many里面对象的时候, 被关联对象也会被取出来, 就会取出来1+N条.
获取Topic里面的内容的时候, 被关联对象category也被取出:
category.java:
package com.bjsxt.hibernate; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import org.hibernate.annotations.BatchSize; @Entity //@BatchSize(size=5) public class Category { private int id; private String name; @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
topic.java:
package com.bjsxt.hibernate; import java.util.ArrayList; import java.util.Date; import java.util.List; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToOne; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.OneToMany; import org.hibernate.annotations.BatchSize; @Entity @NamedQueries( { @NamedQuery(name="topic.selectCertainTopic", query="from Topic t where t.id = :id") } ) /* @NamedNativeQueries( { @NamedNativeQuery(name="topic.select2_5Topic", query="select * from topic limit 2, 5") } ) */ public class Topic { private int id; private String title; private Category category; private Date createDate; private List<Msg> msgs = new ArrayList<Msg>(); @OneToMany(mappedBy="topic") public List<Msg> getMsgs() { return msgs; } public void setMsgs(List<Msg> msgs) { this.msgs = msgs; } public Date getCreateDate() { return createDate; } public void setCreateDate(Date createDate) { this.createDate = createDate; } @ManyToOne public Category getCategory() { return category; } public void setCategory(Category category) { this.category = category; } @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } }
msg.java:
package com.bjsxt.hibernate; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToOne; @Entity public class Msg { private int id; private String cont; private Topic topic; @ManyToOne public Topic getTopic() { return topic; } public void setTopic(Topic topic) { this.topic = topic; } @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public String getCont() { return cont; } public void setCont(String cont) { this.cont = cont; } }
hibernate.cfg.xml:
<?xml version=‘1.0‘ encoding=‘utf-8‘?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost/hibernate</property> <property name="connection.username">root</property> <property name="connection.password">linda0213</property> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <!-- <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property> <property name="connection.url">jdbc:oracle:thin:@localhost:1521:SXT</property> <property name="connection.username">scott</property> <property name="connection.password">tiger</property> <property name="dialect">org.hibernate.dialect.OracleDialect</property> --> <!-- JDBC connection pool (use the built-in) --> <property name="connection.pool_size">1</property> <!-- Enable Hibernate‘s automatic session context management --> <property name="current_session_context_class">thread</property> <!-- Disable the second-level cache --> <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property> <!-- Echo all executed SQL to stdout --> <property name="show_sql">true</property> <property name="format_sql">true</property> <!-- Drop and re-create the database schema on startup <property name="hbm2ddl.auto">update</property> --> <!-- <mapping resource="com/bjsxt/hibernate/Group.hbm.xml"/> <mapping resource="com/bjsxt/hibernate/User.hbm.xml"/> --> <mapping class="com.bjsxt.hibernate.Category"/> <mapping class="com.bjsxt.hibernate.Msg"/> <mapping class="com.bjsxt.hibernate.Topic"/> </session-factory> </hibernate-configuration>
test文件:
package com.bjsxt.hibernate; import java.util.Date; import java.util.List; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import org.hibernate.tool.hbm2ddl.SchemaExport; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; public class HibernateQLTest { private static SessionFactory sf; @BeforeClass public static void beforeClass() { sf = new AnnotationConfiguration().configure().buildSessionFactory(); } @AfterClass public static void afterClass() { sf.close(); } @Test public void testSchemaExport() { new SchemaExport(new AnnotationConfiguration().configure()).create(false, true); } @Test public void testSave() { Session session = sf.openSession(); session.beginTransaction(); for(int i=0; i<10; i++) { Category c = new Category(); c.setName("c" + i); Topic t = new Topic(); t.setCategory(c); t.setTitle("t" + i); t.setCreateDate(new Date()); session.save(c); session.save(t); } session.getTransaction().commit(); session.close(); } //N+1 @Test public void testQuery1() { Session session = sf.openSession(); session.beginTransaction(); //List<Topic> topics = (List<Topic>)session.createCriteria(Topic.class).list(); List<Topic> topics = (List<Topic>)session.createQuery("from Topic").list(); for(Topic t : topics) { System.out.println(t.getId() + "-" + t.getTitle()); } session.getTransaction().commit(); session.close(); } @Test public void testQuery2() { Session session = sf.openSession(); session.beginTransaction(); //List<Topic> topics = (List<Topic>)session.createCriteria(Topic.class).list(); List<Topic> topics = (List<Topic>)session.createQuery("from Topic").list(); for(Topic t : topics) { System.out.println(t.getId() + "-" + t.getTitle()); System.out.println(t.getCategory().getName()); } session.getTransaction().commit(); session.close(); } //@BatchSize @Test public void testQuery3() { Session session = sf.openSession(); session.beginTransaction(); //List<Topic> topics = (List<Topic>)session.createCriteria(Topic.class).list(); List<Topic> topics = (List<Topic>)session.createQuery("from Topic").list(); for(Topic t : topics) { System.out.println(t.getId() + "-" + t.getTitle()); System.out.println(t.getCategory().getName()); } session.getTransaction().commit(); session.close(); } //join fetch @Test public void testQuery4() { Session session = sf.openSession(); session.beginTransaction(); //List<Topic> topics = (List<Topic>)session.createCriteria(Topic.class).list(); List<Topic> topics = (List<Topic>)session.createQuery("from Topic t left join fetch t.category c").list(); for(Topic t : topics) { System.out.println(t.getId() + "-" + t.getTitle()); System.out.println(t.getCategory().getName()); } session.getTransaction().commit(); session.close(); } public static void main(String[] args) { beforeClass(); } }
此时输出结果会顺带打印出 category的查询信息,
Hibernate: select topic0_.id as id2_, topic0_.category_id as category4_2_, topic0_.createDate as createDate2_, topic0_.title as title2_ from Topic topic0_ Hibernate: select category0_.id as id0_0_, category0_.name as name0_0_ from Category category0_ where category0_.id=? Hibernate: select category0_.id as id0_0_, category0_.name as name0_0_ from Category category0_ where category0_.id=? Hibernate: select category0_.id as id0_0_, category0_.name as name0_0_ from Category category0_ where category0_.id=? Hibernate: select category0_.id as id0_0_, category0_.name as name0_0_ from Category category0_ where category0_.id=? Hibernate: select category0_.id as id0_0_, category0_.name as name0_0_ from Category category0_ where category0_.id=? Hibernate: select category0_.id as id0_0_, category0_.name as name0_0_ from Category category0_ where category0_.id=? Hibernate: select category0_.id as id0_0_, category0_.name as name0_0_ from Category category0_ where category0_.id=? Hibernate: select category0_.id as id0_0_, category0_.name as name0_0_ from Category category0_ where category0_.id=? Hibernate: select category0_.id as id0_0_, category0_.name as name0_0_ from Category category0_ where category0_.id=? Hibernate: select category0_.id as id0_0_, category0_.name as name0_0_ from Category category0_ where category0_.id=? 1-t0 2-t1 3-t2 4-t3 5-t4 6-t5 7-t6 8-t7 9-t8 10-t9
解决方案
1. 在topic.java 里many to one下写入fetch=FetchType.LAZY
2. 在test文件里用Creteria替换Query.因为Creteria是表连接的方式, 和4一样.
3. 在category里@Entity下面加上 @BatchSize(size=5), 这样10条记录的话, 发出2条sql就可以了.
4, 使用join fetch:
//join fetch @Test public void testQuery4() { Session session = sf.openSession(); session.beginTransaction(); //List<Topic> topics = (List<Topic>)session.createCriteria(Topic.class).list(); List<Topic> topics = (List<Topic>)session.createQuery("from Topic t left join fetch t.category c").list(); for(Topic t : topics) { System.out.println(t.getId() + "-" + t.getTitle()); System.out.println(t.getCategory().getName()); } session.getTransaction().commit(); session.close(); }
如何选择使用哪个?
lazy:就取对象属性, 不取关联对象的属性
join fetch:马上就用关联对象的属性
标签:
原文地址:http://www.cnblogs.com/wujixing/p/5424980.html