休眠/弹簧:getHibernateTemplate().save(...) 冻结/挂起

ash*_*999 5 mysql spring hibernate transactions freeze

我将 Hibernate 和 Spring 与 DAO 模式一起使用(*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>
Run Code Online (Sandbox Code Playgroud)

Mik*_*e Q 1

当冻结发生时,会中断应用程序,找到主线程并捕获堆栈跟踪。仔细查看,直到您准确地找到正在运行的数据库查询正在被阻塞。

您提到运行测试本身可以正常工作,但运行完整套件会导致问题。如果是这种情况,那么我猜测之前的测试之一仍然有一个事务打开,并且锁定了阻塞测试试图访问的某些行。

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

打开 hibernate.show_sql 选项,以便您可以在控制台中看到正在生成的所有 SQL。

当冻结发生时,您可以找出数据库中哪些行被锁定。例如,在 SQLServer 中,您可以运行sp_lock来查看这一点,并sp_who查看哪些 SQL 进程 ID 正在阻塞另一个进程 ID。