【问题标题】:Spring transactions & hibernate: lazy initializationSpring事务和休眠:延迟初始化
【发布时间】:2010-10-21 21:59:07
【问题描述】:

从我目前所读到的内容中,我了解到使用事务将是解决 hibernate 延迟加载问题的方法。该会话将在服务层的整个事务期间可用,无需进一步说明。

所以也许我错误地配置了我的事务管理?说到 spring 和 hibernate,我实际上是一个新手,但也许你们可以帮助我。

我的配置:

<bean class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
    id="sessionFactory">
    <property name="configLocation">
        <value>classpath:hibernate.cfg.xml</value>
    </property>
</bean>
<!-- Hibernate Template bean that will be assigned to DAOs. -->
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
    <property name="sessionFactory">
        <ref bean="sessionFactory" />
    </property>
</bean>

<!--
    Transaction manager for a single Hibernate SessionFactory (alternative
    to JTA)
-->
<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory">
        <ref local="sessionFactory" />
    </property>
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />

我的 DAO 实现只需要一个 @Repository 注释和一个使用自动装配注入的 Hibernate-template bean。

服务实现的典型标头是:

@Service
@Transactional(readOnly=true)
public class LeerlingServiceImpl implements LeerlingService {

    @Autowired
    LeerlingDAO leerlingDAO;
    @Autowired
    LeerplanDAO leerplanDAO;

如果在该特定方法中实际保存/更新了任何内容,则使用 @Service(readOnly=false) 注释。

我是否需要配置其他内容以确保我可以在我的服务中加载正确的关联,或者这通常由事务处理?

现在我只是对我应该做什么有点困惑,所以请帮助我:)

【问题讨论】:

    标签: java hibernate spring transactions lazy-initialization


    【解决方案1】:

    延迟加载问题和事务并没有真正相互关联。但那是另一个故事:) 除了在 bean 中访问 session 之外,您做得很好。不知道你将如何做到这一点。标准解决方案(在 spring 2.x 中,不确定 3.x,还没有查看)是使用 HibernateDaoSupport 作为类的基类,如果您将有权访问会话。但就我个人而言,这看起来有点狡猾,因为增加了对 Spring 特定类的依赖。更好的方法是将会话注入到您的 bean 中。为此,您需要使用与该类似的定义来声明会话 bean:

    <bean name="hibernateSession" class="org.springframework.orm.hibernate3.SessionFactoryUtils" factory-method="getSession"
      scope="prototype">
        <constructor-arg index="0" ref="hibernateSessionFactory"/>
        <constructor-arg index="1" value="false"/>
        <aop:scoped-proxy/>
    </bean>
    

    然后就使用它。

    以下是详细信息:

    http://stas-blogspot.blogspot.com/2009/10/hibernate-spring-in-standalone.html

    【讨论】:

    • 使用模板不是“标准”解决方案,它只是自 2007 年以来不推荐的一种选择。如果您想无模板,只需注入 sessionFactory 并使用 sessionFactory.getCurrentSession() .见So should you still use Spring's HibernateTemplate and/or JpaTemplate??
    • 为了绕过调用 sessionFactory.getCurrentSession(),间接的数量相当惊人。不知道将 getBean() 插入到 Session 的每个方法调用中会产生什么性能后果。
    • 我一直在我的 DAO 中使用“hibernateDAOSupport”类的扩展(并注入它。)。但是如何让我的会话在我的服务和 DAO 中可用,或者这是一件不自然的事情?其他人建议使用:community.jboss.org/wiki/OpenSessioninView;因为这会将会话绑定到每个请求的线程。(所以是的:我正在制作一个 webapp)
    • @toomuchcs,您发布的配置没有任何明显问题。也许发布一些不起作用的实际代码?扩大交易范围并不是灵丹妙药,您仍然可能会犯很多错误。 OSIV 通常是对延迟加载异常的全面修复,但它确实需要程序员真正了解 ORM 的工作原理以及附加到会话的含义,否则您最终会遇到意外的版本号颠簸和临时数据在您的数据库中。
    • @Pascal Thivent。谢谢你的链接。除了需要手动调用 getCurrentSession 来获取会话之外,我的方法与描述的文章中的方法几乎相同。同意,这没什么区别 :) 我称它为“标准”只是因为 Spring 2.x 文档引用了它。
    【解决方案2】:

    到目前为止,我认为我对 Spring 的理解还很糟糕;我们的会话管理确实没有真正的管理。基本上现在发生的事情是:您可以从 DAO 获取数据,但在收到数据后,您甚至无法加载惰性集合,因为会话已关闭。

    现在我们使用休眠拦截器,它在每个请求开始时将会话附加到线程,并在结束时关闭它。这并不总是最理想的解决方案,但对于学校项目我不会太费心。

    另一种解决方案似乎是:以使用@around 的方式添加AOP,该会话仅在服务方法调用期间可用。我认为这是最好的解决方案,不过,我现在不会为这个项目深入挖掘。好在我知道它的存在。

    这篇文章对我也有很大帮助:http://www.jroller.com/kbaum/entry/orm_lazy_initialization_with_dao

    对于那些感兴趣的人:这是我必须补充的:在 Spring MVC 3.0 中有一个名为 mvc:intereceptors 的新功能,它使我减少了输入 xml。

    <!-- WEB-INF/applicationContext.xml or your own XML config file -->
    <mvc:interceptors>
        <bean
            class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
            <property name="sessionFactory">
                <ref local="sessionFactory" />
            </property>
        </bean>
    </mvc:interceptors>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-19
      • 2013-09-14
      • 2014-01-10
      相关资源
      最近更新 更多