`
Wind_ZhongGang
  • 浏览: 259693 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Hibernate fetch 抓取策略

阅读更多

 


  Hibernate fetch抓取策略定义了当抓取关联对象时,以怎样的一种方式进行抓取。当抓取策略为join时,抓取关联对象是通过连接表来抓取的,只会发送一条sql语句,即可完成主对象与关联对象的抓取,而当抓取策略为select时,抓取关联对象则会发送两条sql语句来完成关联对象的抓取,一条是抓取主对象,而另一条则是抓取关联对象。抓取策略通常会与延迟加载策略合并使用,这是因为当采用延迟加载策略时,如果抓取策略的设置不适当,会造成想象之外的异常,而当采用非延迟加载策略时,即即时加载策略,通常的建议是采用join即连接抓取策略,这样避免了向数据库发送多条sql语句。需要注意的是,只有当使用get或load方法来获取对象时,抓取策略才会起作用,如果查找对象采用的是自定义的hql或sql语句,抓取策略不会起作用。其中get方法是即时加载对象,而load则是延迟加载对象,只有当使用到该对象时,才会向数据库发送查询语句,以查找出该对象。

 

  一。Husband

 

package com.dream.model.join;

import java.util.Set;

/**
 * Created by IntelliJ IDEA.
 * User: Zhong Gang
 * Date: 9/26/11
 * Time: 5:46 PM
 */
public class Husband {
    private Integer id;
    private String name;

    private Set<Wife> wifes;

    public Husband(String name) {
        this.name = name;
    }

    public Husband() {
    }

    public Husband(String name, Set<Wife> wifes) {
        this.name = name;
        this.wifes = wifes;
    }

    public Set<Wife> getWifes() {
        return wifes;
    }

    public Integer getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

 

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping default-access="field">

    <class name="com.dream.model.join.Husband" table="husband" dynamic-insert="true" dynamic-update="true">
        <id name="id" column="id" type="java.lang.Integer">
            <generator class="native"/>
        </id>
        <property name="name" column="name" type="java.lang.String"/>

        <set name="wifes" table="wife" cascade="all" lazy="false" fetch="join">
            <key column="husbandid"/>
            <one-to-many class="com.dream.model.join.Wife"/>
        </set>
    </class>

</hibernate-mapping>

 

  二。Wife

 

package com.dream.model.join;

/**
 * Created by IntelliJ IDEA.
 * User: Zhong Gang
 * Date: 9/26/11
 * Time: 5:47 PM
 */
public class Wife {
    private Integer id;
    private String name;

    private Husband husband;

    public Wife(String name) {
        this.name = name;
    }

    public Wife() {
    }

    public Wife(String name, Husband husband) {
        this.name = name;
        this.husband = husband;
    }

    public String getName() {
        return name;
    }

    public Husband getHusband() {
        return husband;
    }
}

 

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping default-access="field">

    <class name="com.dream.model.join.Wife" table="wife" dynamic-insert="true" dynamic-update="true">
        <id name="id" column="id" type="java.lang.Integer">
            <generator class="native"/>
        </id>
        <property name="name" column="name" type="java.lang.String"/>

        <many-to-one name="husband" class="com.dream.model.join.Husband" column="husbandid"/>
    </class>

</hibernate-mapping>

 

  三。CoupleDao

 

package com.dream.dao.standard;

import com.dream.model.join.Husband;
import com.dream.model.join.Wife;

import java.util.Set;

/**
 * Created by IntelliJ IDEA.
 * User: Zhong Gang
 * Date: 9/26/11
 * Time: 5:51 PM
 */
public interface CoupleDao {

    Husband findHusbandById(Integer id);

    void saveOrUpdateHusband(Husband husband);

}

 

 

package com.dream.dao;

import com.dream.dao.standard.CoupleDao;
import com.dream.model.join.Husband;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: Zhong Gang
 * Date: 9/26/11
 * Time: 5:52 PM
 */
public class CoupleDaoImpl extends HibernateDaoSupport implements CoupleDao {

    public Husband findHusbandById(Integer id) {
         return getHibernateTemplate().get(Husband.class, id);
    }

    public void saveOrUpdateHusband(Husband husband) {
        getHibernateTemplate().saveOrUpdate(husband);
    }
}

 

  四。CoupleService

 

 

package com.dream.service.standard;

import com.dream.model.join.Husband;

/**
 * Created by IntelliJ IDEA.
 * User: Zhong Gang
 * Date: 9/26/11
 * Time: 5:53 PM
 */
public interface CoupleService {

    Husband loadHusbandById(Integer id);

    void saveOrUpdateHusband(Husband husband);
}
 
package com.dream.service;

import com.dream.dao.standard.CoupleDao;
import com.dream.exception.DataNotExistException;
import com.dream.model.join.Husband;
import com.dream.service.standard.CoupleService;

/**
 * Created by IntelliJ IDEA.
 * User: Zhong Gang
 * Date: 9/26/11
 * Time: 5:53 PM
 */
public class CoupleServiceImpl implements CoupleService {
    private CoupleDao coupleDao;

    public Husband loadHusbandById(Integer id) {
        Husband husband = coupleDao.findHusbandById(id);
        if (husband == null) {
            throw new DataNotExistException();
        }
        return husband;
    }

    public void saveOrUpdateHusband(Husband husband) {
        coupleDao.saveOrUpdateHusband(husband);
    }

    public void setCoupleDao(CoupleDao coupleDao) {
        this.coupleDao = coupleDao;
    }
}

 

package com.dream.exception;

/**
 * Created by IntelliJ IDEA.
 * User: Zhong Gang
 * Date: 9/26/11
 * Time: 6:01 PM
 */
public class DataNotExistException extends RuntimeException {

    public DataNotExistException() {
        super("The data you find does not exist in the database.");
    }
}
 

 

  五。testDatasource

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"
       default-autowire="byName">

    <context:property-placeholder location="classpath:testDB.properties"/>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
          destroy-method="close">
        <property name="driverClassName" value="${db.driver}"/>
        <property name="url" value="${db.url}"/>
        <property name="username" value="${db.username}"/>
        <property name="password" value="${db.password}"/>
    </bean>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="mappingLocations">
            <list>
                <value>/hibernate_mappings/Husband.hbm.xml</value>
                <value>/hibernate_mappings/Wife.hbm.xml</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
                <prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop>
            </props>
        </property>
    </bean>

    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

    <aop:config>
        <aop:pointcut id="service" expression="execution(* com.dream.service..*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="service"/>
    </aop:config>

    <bean id="coupleDao" class="com.dream.dao.CoupleDaoImpl">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <bean id="coupleService" class="com.dream.service.CoupleServiceImpl">
        <property name="coupleDao" ref="coupleDao"/>
    </bean>
</beans>

 

  六。testDB

 

db.url=jdbc:mysql://localhost:3306/test_fetch

db.driver=com.mysql.jdbc.Driver

db.username=root

db.password=root

hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

hibernate.show_sql=true

hibernate.hbm2ddl.auto=update

hibernate.jdbc.batch_size=100

 

  七。TestCase

 

 

package com.fetch;

import com.dream.model.join.Husband;
import com.dream.model.join.Wife;
import com.dream.service.standard.CoupleService;
import junit.framework.TestCase;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.HashSet;
import java.util.Set;

/**
 * Created by IntelliJ IDEA.
 * User: Zhong Gang
 * Date: 9/26/11
 * Time: 6:05 PM
 */
public class HibernateFetchTest extends TestCase {
    private CoupleService coupleService;

    @Override
    public void setUp() throws Exception {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:testDatasource.xml");
        coupleService = (CoupleService) context.getBean("coupleService");
    }

    public void testCascadeAllDelete() throws Exception {
        Wife wife1 = new Wife("Wife1");
        Wife wife2 = new Wife("Wife2");

        Set<Wife> wifes = new HashSet<Wife>();
        wifes.add(wife1);
        wifes.add(wife2);

        Husband husband = new Husband("Husband1", wifes);

        coupleService.saveOrUpdateHusband(husband);

        Husband husbandAfterFound = coupleService.loadHusbandById(husband.getId());
        Set<Wife> wifeSet = husbandAfterFound.getWifes();
        assertEquals(2, wifeSet.size());
    }
}
 
  Scenario 1:lazy="true" fetch="join"
  
Hibernate: insert into husband (name) values (?)
Hibernate: insert into wife (name) values (?)
Hibernate: insert into wife (name) values (?)
Hibernate: update wife set husbandid=? where id=?
Hibernate: update wife set husbandid=? where id=?
Hibernate: select husband0_.id as id0_1_, husband0_.name as name0_1_, wifes1_.husbandid as husbandid0_3_, wifes1_.id as id3_, wifes1_.id as id1_0_, wifes1_.name as name1_0_, wifes1_.husbandid as husbandid1_0_ from husband husband0_ left outer join wife wifes1_ on husband0_.id=wifes1_.husbandid where husband0_.id=?
  只发送了一条sql语句便查找出了主对象及关联对象。
 
  Scenario 2:lazy="true" fetch="select"
  
Hibernate: insert into husband (name) values (?)
Hibernate: insert into wife (name) values (?)
Hibernate: insert into wife (name) values (?)
Hibernate: update wife set husbandid=? where id=?
Hibernate: update wife set husbandid=? where id=?
Hibernate: select husband0_.id as id0_0_, husband0_.name as name0_0_ from husband husband0_ where husband0_.id=?

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.dream.model.join.Husband.wifes, no session or session was closed
	at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
	at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
	at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:122)
	at org.hibernate.collection.PersistentSet.size(PersistentSet.java:162)
	at com.fetch.HibernateFetchTest.testCascadeAllDelete(HibernateFetchTest.java:42)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at com.intellij.junit3.JUnit3IdeaTestRunner.doRun(JUnit3IdeaTestRunner.java:139)
	at com.intellij.junit3.JUnit3IdeaTestRunner.startRunnerWithArgs(JUnit3IdeaTestRunner.java:52)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:199)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:62)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
   当采用延迟加载策略的同时,使用select抓取策略时,因为只有当对象使用时才会发起sql语句,这时因为没有了session的管理,会造成异常。

  Scenario 3:lazy="false" fetch="join"
  
Hibernate: insert into husband (name) values (?)
Hibernate: insert into wife (name) values (?)
Hibernate: insert into wife (name) values (?)
Hibernate: update wife set husbandid=? where id=?
Hibernate: update wife set husbandid=? where id=?
Hibernate: select husband0_.id as id0_1_, husband0_.name as name0_1_, wifes1_.husbandid as husbandid0_3_, wifes1_.id as id3_, wifes1_.id as id1_0_, wifes1_.name as name1_0_, wifes1_.husbandid as husbandid1_0_ from husband husband0_ left outer join wife wifes1_ on husband0_.id=wifes1_.husbandid where husband0_.id=?
  使用即时加载策略的同时,使用连接抓取策略,只会发送一条连接sql语句便会查找出主对象及关联对象。

  Scenario 4:lazy="false" fetch="select"
  
Hibernate: insert into husband (name) values (?)
Hibernate: insert into wife (name) values (?)
Hibernate: insert into wife (name) values (?)
Hibernate: update wife set husbandid=? where id=?
Hibernate: update wife set husbandid=? where id=?
Hibernate: select husband0_.id as id0_0_, husband0_.name as name0_0_ from husband husband0_ where husband0_.id=?
Hibernate: select wifes0_.husbandid as husbandid0_1_, wifes0_.id as id1_, wifes0_.id as id1_0_, wifes0_.name as name1_0_, wifes0_.husbandid as husbandid1_0_ from wife wifes0_ where wifes0_.husbandid=?
   使用即时加载策略的同时,使用select抓取策略,会发送两条sql语句,第一条用于查询出主对象,而第二条则会查询出关联对象。

 

0
1
分享到:
评论

相关推荐

    Hibernate学习总结

    学习成长路,Hibernate总结: 1.Hibernate入门优缺点、 2.Hibernate的操作CRUD、 3.主键生成机制、 4.持久化对象的状态、 ...8.Hibernate检索策略(fetch抓取策略)、 9.二级缓存、 10.Hbernate的检索方式(HQL语句)

    Hibernate+中文文档

    19.1.2. 调整抓取策略(Tuning fetch strategies) 19.1.3. 单端关联代理(Single-ended association proxies) 19.1.4. 实例化集合和代理(Initializing collections and proxies) 19.1.5. 使用批量抓取(Using...

    hibernate3.2中文文档(chm格式)

    19.1.2. 调整抓取策略(Tuning fetch strategies) 19.1.3. 单端关联代理(Single-ended association proxies) 19.1.4. 实例化集合和代理(Initializing collections and proxies) 19.1.5. 使用批量抓取(Using...

    HibernateAPI中文版.chm

    19.1.2. 调整抓取策略(Tuning fetch strategies) 19.1.3. 单端关联代理(Single-ended association proxies) 19.1.4. 实例化集合和代理(Initializing collections and proxies) 19.1.5. 使用批量抓取(Using...

    Hibernate 中文 html 帮助文档

    19.1.2. 调整抓取策略(Tuning fetch strategies) 19.1.3. 单端关联代理(Single-ended association proxies) 19.1.4. 实例化集合和代理(Initializing collections and proxies) 19.1.5. 使用批量抓取(Using...

    Hibernate中文详细学习文档

    19.1.2. 调整抓取策略(Tuning fetch strategies) 19.1.3. 单端关联代理(Single-ended association proxies) 19.1.4. 实例化集合和代理(Initializing collections and proxies) 19.1.5. 使用批量抓取(Using...

    最全Hibernate 参考文档

    19.1.1. 调整抓取策略(Tuning fetch strategies) 19.1.2. 单端关联代理(Single-ended association proxies) 19.1.3. 实例化集合和代理(Initializing collections and proxies) 19.1.4. 使用批量抓取(Using...

    hibernate 体系结构与配置 参考文档(html)

    1. Hibernate入门 1.1. 前言 1.2. 第一部分 - 第一个Hibernate应用程序 1.2.1. 第一个class 1.2.2. 映射文件 1.2.3. Hibernate配置 1.2.4. 用Ant构建 1.2.5. 启动和辅助类 1.2.6. 加载并存储对象 1.3. 第...

    Hibernate教程

    20.1.2. 调整抓取策略(Tuning fetch strategies) 20.1.3. 单端关联代理(Single-ended association proxies) 20.1.4. 实例化集合和代理(Initializing collections and proxies) 20.1.5. 使用批量抓取(Using...

    Hibernate_3.2.0_符合Java习惯的关系数据库持久化

    19.1.2. 调整抓取策略(Tuning fetch strategies) 19.1.3. 单端关联代理(Single-ended association proxies) 19.1.4. 实例化集合和代理(Initializing collections and proxies) 19.1.5. 使用批量抓取(Using...

    hibernate总结

    i. 如果不加fetch关键字,则hibernate不会抓取关系属性,但会遍历关系属性所对应的表 ii. 不加fetch关键字时,select 要指定返回的对象,否则它要返回数组 iii. 条件:持久化类之间有关系属性映射 Hibernate级联...

    Hibernate3+中文参考文档

    19.1.1. 调整抓取策略(Tuning fetch strategies) 19.1.2. 单端关联代理(Single-ended association proxies) 19.1.3. 实例化集合和代理(Initializing collections and proxies) 19.1.4. 使用批量抓取(Using...

    hibernate3.04中文文档.chm

    20.1.2. 调整抓取策略(Tuning fetch strategies) 20.1.3. 单端关联代理(Single-ended association proxies) 20.1.4. 实例化集合和代理(Initializing collections and proxies) 20.1.5. 使用批量抓取...

    hibernate 框架的基础四

    HQL的多表检索 事务及隔离级别 HQL优化 抓取策略

    hibernate 框架详解

    目录 前言 1.... 2.... 1. 在Tomcat中快速上手 ... 1.1. 开始Hibernate之旅 1.2.... 1.3.... 1.4.... 调整抓取策略(Tuning fetch strategies) 20.1.3. 单端关联代理(Single-ended association proxies) ...

    Hibernate参考文档

    19.1.2. 调整抓取策略(Tuning fetch strategies) 19.1.3. 单端关联代理(Single-ended association proxies) 19.1.4. 实例化集合和代理(Initializing collections and proxies) 19.1.5. 使用批量抓取(Using...

    NHibernate参考文档 2.0.0 chm

    16.1.2. 调整抓取策略(Tuning fetch strategies) 16.1.3. 单端关联代理(Single-ended association proxies) 16.1.4. 初始化集合和代理(Initializing collections and proxies) 16.1.5. 使用批量抓取(Using ...

    NHibernate中文帮组文档(2008.11月更新)

    16.1.2. 调整抓取策略(Tuning fetch strategies) 16.1.3. 单端关联代理(Single-ended association proxies) 16.1.4. 初始化集合和代理(Initializing collections and proxies) 16.1.5. 使用批量抓取(Using ...

Global site tag (gtag.js) - Google Analytics