Hibernate / Spring:getHibernateTemplate()。save(...)冻结/挂起

时间:2011-01-08 17:48:30

标签: mysql hibernate spring transactions freeze

我正在使用带有DAO模式的Hibernate和Spring(* DAO.java类中的所有Hibernate依赖项)。我有九个单元测试(JUnit),它们创建一些业务对象,保存它们,并对它们执行操作;对象都在哈希中(所以我一直在重复使用相同的对象)。

我的JUnit设置方法调用我的DAO.deleteAllObjects()方法,该方法为我的业务对象表(只有一个)调用getSession().createSQLQuery("DELETE FROM <tablename>").executeUpdate()

我的一个单元测试(#8/9)冻结了。我认为这是一个数据库死锁,因为Hibernate日志文件最后显示我的删除语句。然而,调试显示它只是HibernateTemplate.save(someObject)冻结了。 (Eclipse显示它在 HibernateTemplate.save(Object),第694行时冻结。)

另外值得注意的是,单独运行此测试(不在9个测试的套件中)不会导致任何问题。

我该如何排除故障并解决此问题?

另外,如果重要的话,我正在使用@Entity注释。

编辑:我删除了业务对象的重用(在每种方法中使用唯一对象) - 没有任何区别(仍然冻结)。

编辑:这也开始流入其他测试(不能运行多个测试类而不会冻结某些东西)

编辑:将冻结测试分成两个类。我现在要这样做,因为可耻的非干,因为有两个或更多测试类对同一个业务对象类进行单元测试。

交易配置:

    <bean id="txManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <tx:advice id="txAdvice" transaction-manager="txManager">
        <!-- the transactional semantics... -->
        <tx:attributes>
            <!-- all methods starting with 'get' are read-only -->
            <tx:method name="get*" read-only="true" />
            <tx:method name="find*" read-only="true" />
            <!-- other methods use the default transaction settings (see below) -->
            <tx:method name="*" />
        </tx:attributes>
    </tx:advice>

    <!-- my bean which is exhibiting the hanging behavior -->
    <aop:config>
    <aop:pointcut id="beanNameHere"
        expression="execution(* com.blah.blah.IMyDAO.*(..))" />
    <aop:advisor advice-ref="txAdvice" pointcut-ref="beanNameHere" />
</aop:config>

2 个答案:

答案 0 :(得分:1)

当冻结发生时,破坏应用程序,找到主线程并捕获堆栈跟踪。直到找到正在运行的正在运行的数据库中阻塞的数据库查询。

你提到运行测试它自己的工作正常但运行完整套件会导致问题。如果是这种情况,那么我猜测其中一个先前的测试仍然打开了一个事务,并且在阻塞测试试图访问的某些行上有锁定。

您的测试是否同时运行?如果是这样就停止这样做,因为它们可能互相干扰。

启用hibernate.show_sql选项,以便在控制台中查看正在生成的所有SQL。

在冻结发生时,您可以找出DB中锁定的行。例如在SQLServer中,您可以运行sp_lock来查看此内容,并sp_who查看哪些SQL进程ID在另一个上阻止。

答案 1 :(得分:1)

要检查的一些事项:

  • 正确的事务管理 - 在您的配置中,您可以通过DAO进行交易。通常,建议您在服务层周围进行交易,而不是DAO。但无论如何 - 确保测试使用的dao周围有一个事务。或者进行测试@Transactional(如果使用spring的junit runner)

  • 将数据源的日志记录阈值更改为info(c3p0,也许?)。它报告了死锁。

  • 观察数据库日志是否存在死锁(如果有这样的选项)