Hibernate lazyロードFOR Connection


Hibernate          :

      ,         ,   :true/false/extra

true:    ,                        ,       ,   
            
false:       ,         ,                    
extra:            ,      size/contains      ,hibernate
                   ,         SQL  ,        ,   
                         ,                 

 
 
以下では、一方向の一対のマルチマッピングに基づいています.一方のsetに対してlazyの関連設定を行い,テストを行う.
次のようになります.
package com.bjsxt.hibernate;

import java.util.Set;

public class Classes {
	
	private int id;
	
	private String name;
	
	private Set students;
	
	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 Set getStudents() {
		return students;
	}

	public void setStudents(Set students) {
		this.students = students;
	}
	
	
}

 
package com.bjsxt.hibernate;

public class Student {
	
	private int id;
	
	private String name;

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

 
 
Classes.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="com.bjsxt.hibernate.Classes" table="t_classes">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
		<!-- 
			<set name="students" cascade="all" order-by="id">
		 -->
		 <set name="students" lazy="extra">
			<key column="classid"/>
			<one-to-many class="com.bjsxt.hibernate.Student"/>
		</set>
	</class>
</hibernate-mapping>

 
Student.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="com.bjsxt.hibernate.Student" table="t_student">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
	</class>
</hibernate-mapping>

 
 
以上、一対のマルチマッピングを構成しました.
集合の下でLAZYに3つの属性値true/false/extraを設定できるので,それぞれテストを行う.
1、true:デフォルト値です.このコレクションを呼び出して中の要素オブジェクトを取得した場合にのみ、クエリー文を発行し、そのコレクション要素のデータをロードすることを意味します.
 
package com.bjsxt.hibernate;

import java.util.Iterator;
import java.util.Set;

import org.hibernate.Session;

import junit.framework.TestCase;

/**
 *   lazy    
 * @author Administrator
 *
 */
public class CollectionLazyTest1 extends TestCase {
	
	public void testLoadClasses1() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			
			//      sql
			Classes classes = (Classes)session.load(Classes.class, 1);
			
			//       sql,     classes
			System.out.println("  :【" + classes.getName() + "】       :");
			
			//      sql
			Set students = classes.getStudents();
			
			//       sql,     Students
			for (Iterator iter = students.iterator(); iter.hasNext();) {
				Student student = (Student)iter.next();
				System.out.println(student.getName());
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}	
	}
	
	public void testLoadClasses2() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			
			//      sql
			Classes classes = (Classes)session.load(Classes.class, 1);
			
			//       sql,     classes
			System.out.println("  :【" + classes.getName() + "】         :");

			//      sql	
			Set students = classes.getStudents();
			
			//       sql,        Students
			System.out.println(students.size());
			
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}	
	}
	
}

上記の2つの方法の結果は、次のとおりです.
testLoadClass 1結果:
Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.id=?
  :【  】       :
Hibernate: select students0_.classid as classid0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_ from t_student students0_ where students0_.classid=?
  _6
  _9
  _2
  _0
  _4
  _1
  _8
  _7
  _5
  _3

 
testLoadClass 2結果:
Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.id=?
  :【  】         :
Hibernate: select students0_.classid as classid0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_ from t_student students0_ where students0_.classid=?
10

 
2、false:オブジェクトをロードしながら、2番目のクエリー文を発行して関連セットのデータをロードする怠惰なロードプロパティをキャンセルします.
package com.bjsxt.hibernate;

import java.util.Iterator;
import java.util.Set;

import org.hibernate.Session;

import junit.framework.TestCase;

/**
 *       lazy=false
 * @author Administrator
 *
 */
public class CollectionLazyTest2 extends TestCase {
	
	public void testLoadClasses1() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			
			//      sql
			Classes classes = (Classes)session.load(Classes.class, 1);
			
			//       sql,     classes Students 
			System.out.println("  :【" + classes.getName() + "】       :");
			
			//      sql
			Set students = classes.getStudents();
			
			//      sql
			for (Iterator iter = students.iterator(); iter.hasNext();) {
				Student student = (Student)iter.next();
				System.out.println(student.getName());
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}	
	}
	
	public void testLoadClasses2() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			
			//      sql
			Classes classes = (Classes)session.load(Classes.class, 1);
			
			//       sql,     classes Students 
			System.out.println("  :【" + classes.getName() + "】         :");

			//      sql	
			Set students = classes.getStudents();
			
			//      sql	
			System.out.println(students.size());
			
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}	
	}
	
}

ここでtestLoadClass 1メソッドはclassesを呼び出す.getName()の場合、次のように2つのSQLが発行されます.
Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.id=?
Hibernate: select students0_.classid as classid0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_ from t_student students0_ where students0_.classid=?
  :【  】       :
  _3
  _9
  _4
  _6
  _5
  _1
  _8
  _0
  _2
  _7

testLoadClass 2の結果も以下の通りです.この2つのSQLもclassesを呼び出していることに注意してください.getNameで発行され、後でstudentsが印刷されます.sizeはSQLを再発行しませんでした.これは、オブジェクトをロードすると同時に、2番目のクエリー文を発行して関連セットのデータをロードすることを意味します.
Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.id=?
Hibernate: select students0_.classid as classid0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_ from t_student students0_ where students0_.classid=?
  :【  】         :
10

 
 
3、extra:集合のsize/containsなどのメソッドを呼び出すと、hibernateは集合全体のデータをロードするのではなく、必要な値を得るために賢いSQL文を発行します.これらの集合要素オブジェクトデータを本当に使用する必要がある場合にのみ、クエリー文を発行してすべてのオブジェクトのデータをロードする
package com.bjsxt.hibernate;

import java.util.Iterator;
import java.util.Set;

import org.hibernate.Session;

import junit.framework.TestCase;

/**
 *       lazy=extra
 * @author Administrator
 *
 */
public class CollectionLazyTest3 extends TestCase {
	
	public void testLoadClasses1() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			
			//      sql
			Classes classes = (Classes)session.load(Classes.class, 1);
			
			//       sql,     classes
			System.out.println("  :【" + classes.getName() + "】       :");
			
			//      sql
			Set students = classes.getStudents();
			
			//       sql,     students
			for (Iterator iter = students.iterator(); iter.hasNext();) {
				Student student = (Student)iter.next();
				System.out.println(student.getName());
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}	
	}
	
	public void testLoadClasses2() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			
			//      sql
			Classes classes = (Classes)session.load(Classes.class, 1);
			
			//       sql,     classes
			System.out.println("  :【" + classes.getName() + "】         :");

			//      sql	
			Set students = classes.getStudents();
			
			//            sql, :
			//select count(id) from t_student where classid =?
			System.out.println(students.size());
			
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}	
	}
	
	public void testLoadClasses3() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			
			//      sql
			Classes classes = (Classes)session.load(Classes.class, 1);
			
			//       sql,     classes
			System.out.println("  :【" + classes.getName() + "】         :");

			//      sql	
			Set students = classes.getStudents();

			//     SQL
			for (Iterator iter = students.iterator(); iter.hasNext();) {
				Student student = (Student)iter.next();
				System.out.println(student.getName());
			}
			
			//               ,       sql, testLoadClasses2                。
			System.out.println(students.size());
			
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			HibernateUtils.closeSession(session);
		}	
	}
	
}

 
testLoadClass 1結果:
Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.id=?
  :【  】       :
Hibernate: select students0_.classid as classid0_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_ from t_student students0_ where students0_.classid=?
  _2
  _8
  _3
  _5
  _4
  _9
  _0
  _7
  _1
  _6

testLoadClass 2結果:
Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.id=?
  :【  】         :
Hibernate: select count(id) from t_student where classid =?
10

 
 
LAZY=「extra」の場合、スマートなstudentsが見られます.size()の場合、select count(id)from t_が呼び出されますstudent where classid =?総数を求める.
3つの値設定の違いと関連を比較すると、3つ目の方法がより最適化されていることが明らかになります.