Hibernate的1+N问题:
fetch=FetchType.eager配置下,取某对象(Student)的自身属性,仍会导致其关联对象(Group)一并查询,本来只需要发1条SQL语句即可完成,结果却发了1+N条SQL语句,影响性能。
解决方法:
1.fetch = FetchType.lazy , 开始只发关于本表的SQL语句,即等用到关联对象时,再发关联表的SQL语句。
2.在关联对象类上标注@BatchSize(size=x) , 设置管理对象查询时一次性查询多少条记录, 使转为为 1+n/x问题。(不推荐)
3.join fetch , 如 使用"from Student s left join fetch s.group g", 进行表连接查询,此时就发1条SQL语句。
fetch=FetchType.eager配置下,取某对象(Student)的自身属性,仍会导致其关联对象(Group)一并查询,本来只需要发1条SQL语句即可完成,结果却发了1+N条SQL语句,影响性能。
解决方法:
1.fetch = FetchType.lazy , 开始只发关于本表的SQL语句,即等用到关联对象时,再发关联表的SQL语句。
2.在关联对象类上标注@BatchSize(size=x) , 设置管理对象查询时一次性查询多少条记录, 使转为为 1+n/x问题。(不推荐)
3.join fetch , 如 使用"from Student s left join fetch s.group g", 进行表连接查询,此时就发1条SQL语句。
4.使用QBC查询,默认效果与3相同。
JUnit测试类:
import java.util.List;
import org.hibernate.Session;
import org.junit.Test;
import com.ekunt.Util.HibernateUtil;
import com.ekunt.entity.Group;
import com.ekunt.entity.Student;
/**
* 演示Hibernate的1+N问题:
* fetch=FetchType.eager配置下,
* 取某对象(Student)的自身属性,仍会导致其关联对象(Group)一并查询,
* 本来只需要发1条SQL语句即可完成,结果却发了1+N条SQL语句,影响性能。
*
* 解决方法:
* 1.fetch = FetchType.lazy , 开始只发关于本表的SQL语句,即等用到关联对象时,再发关联表的SQL语句。
* 2.在关联对象类上标注@BatchSize(size=x) , 设置管理对象查询时一次性查询多少条记录, 使转为为 1+n/x问题。(不推荐)
* 3.join fetch , 如 使用"from Student s left join fetch s.group g", 进行表连接查询,此时就发1条SQL语句。
* 4.使用QBC查询,默认效果与3相同。
*
* @author E-Kunt
*
*/
public class HibernateTest {
@Test
public void saveTest(){
Group g1 = new Group("JAVA","JavaSE");
Group g2 = new Group("ASP.NET","ASP.NET3.5");
Student s1 = new Student("古月哥欠",35);
Student s2 = new Student("纠结伦",45);
s1.setGroup(g1);
s2.setGroup(g2);
Session session = HibernateUtil.getSession();
session.beginTransaction();
session.save(g1);
session.save(g2);
session.save(s1);
session.save(s2);
session.getTransaction().commit();
HibernateUtil.closeSession(session);
}
@Test
public void queryTest() {
Session session = HibernateUtil.getSession();
List<Student> students = session.createQuery("from Student").list();
for(Student s : students) {
System.out.println(s.getId() + "-" + s.getName());
}
}
/**
* 1+N问题解决方法3
*/
@Test
public void joinFetchTest() {
Session session = HibernateUtil.getSession();
List<Student> students = session.createQuery("from Student s left join fetch s.group g").list();
for(Student s : students) {
System.out.println(s.getId() + "-" + s.getName());
}
}
/**
* 1+N问题解决方法4
*/
@Test
public void QBCTest() {
Session session = HibernateUtil.getSession();
List<Student> students = session.createCriteria(Student.class).list();
for(Student s : students) {
System.out.println(s.getId() + "-" + s.getName());
}
}
}
小组实体类:
package com.ekunt.entity;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.BatchSize;
@Entity
@Table(name="t_group")
//@BatchSize(size=2) //1+N问题解决方法2
public class Group implements Serializable {
private int id;
private String name;
private String description;
public Group() {
}
public Group(String name, String description) {
this.name = name;
this.description = description;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public String toString() {
return "Group [id=" + id + ", name=" + name + ", description=" + description + "]";
}
}
学生实体类:
package com.ekunt.entity;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="t_student")
public class Student implements Serializable {
private int id;
private String name;
private int age;
private Group group;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@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;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@ManyToOne//(fetch=FetchType.LAZY) //1+N问题解决方法1
@JoinColumn(name="group_id")
public Group getGroup() {
return group;
}
public void setGroup(Group group) {
this.group = group;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
辅助工具类:
package com.ekunt.Util;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
public class HibernateUtil {
private static SessionFactory sessionFactory;
private static Session session;
/**
* 创建Configuration对象,读取hibernate.cfg.xml文件,完成初始化
*/
static{
Configuration cfg = new Configuration().configure();
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();
sessionFactory = cfg.buildSessionFactory(serviceRegistry);
}
/**
* 获取SessionFactory
* @return SessionFactory
*/
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
/**
* 获取Session
* @return Session
*/
public static Session getSession() {
session = sessionFactory.openSession();
return session;
}
/**
* 关闭Session
*/
public static void closeSession(Session session) {
if(session != null) {
session.close();
session = null;
}
}
}