您的位置:首页 > 数据库

Hibernate的1+N(N+1)问题与解决方法

2016-05-10 18:29 375 查看
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相同。

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;
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hibernate 数据库 hql qbc 1+n