<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.com.test.model">
<class name="Student" table="t_student">
<id name="id">
<!-- <generator class="assigned"/> --><!-- 这个需要开发人员自己定义id -->
<generator class="native"/> <!-- 会自动生成一个字符串,此时主键必须为字符串 -->
</id>
<property name="name"/>
<property name="sex"/>
<many-to-one name="classroom" column="c_id" fetch="join"/>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.com.test.model">
<class name="Classroom" table="t_classroom" ><!-- batch-size="20" -->
<id name="id">
<!-- <generator class="assigned"/> --><!-- 这个需要开发人员自己定义id -->
<generator class="native"/> <!-- 会自动生成一个字符串,此时主键必须为字符串 -->
</id>
<property name="name"/>
<property name="grade"/>
<set name="students" lazy="extra" inverse="true" fetch="subselect"><!-- batch-size="400" -->
<key column="c_id"/>
<one-to-many class="Student"/>
</set>
<many-to-one name="special" column="s_id" fetch="join"/>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.com.test.model">
<class name="Special" table="t_special">
<id name="id">
<!-- <generator class="assigned"/> --><!-- 这个需要开发人员自己定义id -->
<generator class="native"/> <!-- 会自动生成一个字符串,此时主键必须为字符串 -->
</id>
<property name="name"/>
<property name="type"/>
<set name="classrooms" lazy="extra" inverse="true">
<key column="s_id"/>
<one-to-many class="Classroom"/>
</set>
</class>
</hibernate-mapping>
package org.com.test.test;
import java.util.List;
import org.com.test.model.Classroom;
import org.com.test.model.Student;
import org.com.test.util.HibernateUtil;
import org.hibernate.Session;
import org.junit.Test;
/**
*
* @author asus_n56 基于xml配置的
*
*/
public class TestFetch {
@Test
public void test01(){
Session session = null;
try {
/**
* 默认情况下使用它三条语句,一条取Student,一条取Classroom,一条取Special;
* 可以通过<many-to-one name="classroom" column="c_id" fetch="join"/>
* 可以通过<many-to-one name="special" column="s_id" fetch="join"/>来设置抓取策略。(此时一条Sql就可以取完了 )
*/
session = HibernateUtil.getSession();
session.beginTransaction();
Student s = (Student)session.load(Student.class, 1);
System.out.println(s.getName()+":"+s.getClassroom().getName()+":"+s.getClassroom().getSpecial().getName());
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtil.closeSession(session);
}
}
@Test
public void test02(){
Session session = null;
try {
/**
* 默认情况下使用它三条语句,一条取Student,一条取Classroom,一条取Special;
* 可以通过<many-to-one name="classroom" column="c_id" fetch="join"/>
* 可以通过<many-to-one name="special" column="s_id" fetch="join"/>来设置抓取策略。(此时一条Sql就可以取完了 )
* 特别注意:当我们使用fetch=join来设置抓取策略的时候,可以抓取关联对象,但是如果我们不使用关联对象的时候,它还是发送一条
* 长长的语句取出所有关联的对象。
*/
session = HibernateUtil.getSession();
session.beginTransaction();
Student s = (Student)session.load(Student.class, 1);
//延迟加载失效
System.out.println(s.getName());
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtil.closeSession(session);
}
}
@SuppressWarnings("unchecked")
@Test
public void test03(){
Session session = null;
try {
/**
* 在xml中配置的fetch=join仅仅是对load的对象有用,对HQL查询的对象没有用。所以会发出查询班级的sql。
* 解决这种问题有两种方案:一种是设置对象的抓取的batch-size
* 另一种方案:在HQL中使用fetch来指定抓取
*/
session = HibernateUtil.getSession();
session.beginTransaction();
List<Student> stus = session.createQuery("from Student").list();
for (Student stu : stus) {
//System.out.println(stu.getName());
System.out.println(stu.getName()+";"+stu.getClassroom());
}
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtil.closeSession(session);
}
}
@SuppressWarnings("unchecked")
@Test
public void test04(){
Session session = null;
try {
/**
* 在xml中配置的fetch=join仅仅是对load的对象有用,对HQL查询的对象没有用。所以会发出查询班级的sql。
* 解决这种问题有两种方案:一种是设置对象的抓取的batch-size
* 另一种方案:在HQL中使用fetch来指定抓取
* 特别注意:使用了join fetch 就不能使用count(*)
*/
session = HibernateUtil.getSession();
session.beginTransaction();
List<Student> stus = session.createQuery("select stu from Student stu join fetch stu.classroom").list();
for (Student stu : stus) {
System.out.println(stu.getName()+";"+stu.getClassroom());
}
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtil.closeSession(session);
}
}
/*
* ************************************************基于1的一方查询**************************************************
*/
@SuppressWarnings("unchecked")
@Test
public void test05(){
Session session = null;
try {
/**
* 对于通过HQL取班级列表并且获取相应的学生列表时,fecth=join就无效了
* 第一种方案可以设置set的batch-size来完成批量的抓取
* 第二中方案可以设置fetch=subselect,使用subselect会完成根据查询出来的班级进行一次对学生对象的子查询
* <set name="students" lazy="extra" inverse="true" fetch="subselect"><!-- batch-size="400" -->
* <key column="c_id"/>
* <one-to-many class="Student"/>
*</set>
*/
session = HibernateUtil.getSession();
session.beginTransaction();
List<Classroom> clas = session.createQuery("from Classroom").list();
for (Classroom cla : clas) {
System.out.println(cla.getName());
for (Student stu : cla.getStudents()) {
System.out.println(stu.getName());
}
}
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtil.closeSession(session);
}
}
}