Spring & Hibernate - 使本机查询在与@Transactional 相同的事务中运行

Posted

技术标签:

【中文标题】Spring & Hibernate - 使本机查询在与@Transactional 相同的事务中运行【英文标题】:Spring & Hibernate - Make native queries run in the same transaction as @Transactional 【发布时间】:2017-02-17 08:51:44 【问题描述】:

是否可以使用通过@Transactional 创建的现有事务来创建本机查询? 这里的大多数问题似乎都与进行原生查询有关。此外,来自Spring + Hibernate Transaction -- Native SQL rollback failure 的答案表明这可能是不可能的。

我测试隔离的方法是运行一些删除操作并添加断点来调查数据库。

这是我目前尝试过的:

@Transactional(value = "someManager")
public class SpringJpaSomeDao implements SomeDao 

@PersistenceContext(unitName = "someUnit")
@Qualifier("entityManagerFactorySome")
private EntityManager em;


@Resource
@Qualifier("someManager")
private PlatformTransactionManager transactionManager;

@Override
@Transactional(value = "someManager", propagation = Propagation.SUPPORTS)
public void runNative(String sql)
    TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
    transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
    transactionTemplate.execute(new TransactionCallbackWithoutResult() 

        @Override

        protected void doInTransactionWithoutResult(TransactionStatus status) 

            em.createNativeQuery(sql).executeUpdate();

        

    );






persistence.xml 的一部分

<persistence-unit name="someUnit" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <non-jta-data-source>java:comp/env/jdbc/someDS</non-jta-data-source>
    <!-- some classes here -->
    <exclude-unlisted-classes>true</exclude-unlisted-classes>
    <properties>
        <!-- some dialect -->
    </properties>
</persistence-unit>

代码是从一些控制器调用的,该控制器也有 @Transactional 注释,将删除操作提供给 Dao。

@Transactional(value = "someManager", propagation = Propagation.SUPPORTS)
public void deleteEntireDatabase() 

    List<String> deletions = new ArrayList<>();
    deletions.add("DELETE FROM something;");


    for (String currentDeletion : deletions) 
        someDao.runNative(currentDeletion);
    




@Override
@Transactional(value = "someManager", propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public void deleteAndFill(JobExecutionProgress progress) 
    deleteEntireDatabase();
    // more code

摘自spring-dao.xml:

<tx:annotation-driven  />

<bean id="entityManagerFactorySome" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="someDataSource" />
    <property name="persistenceUnitName" value="someUnit" />
    <property name="jpaProperties">
        <props>
            <!-- some dialect -->
        </props>
    </property>
</bean>

<bean id="someDao" class="xyz.model.controller.SpringJpaSomeDao"/>

<bean id="someManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactorySome" />
    <qualifier value="someManager"></qualifier>
</bean>


<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

当然,我也尝试了一些变种,比如不同的Propagations,使用从别处获取的entityManager:

    EntityManagerFactory emf = ((JpaTransactionManager) transactionManager).getEntityManagerFactory();

    EntityManager em2 = EntityManagerFactoryUtils.getTransactionalEntityManager(emf);

现在,如果其他一切都失败了,我会做的是手动事务管理。

这是否适用于您的某个应用程序,或者不知道这是否是设置问题?

【问题讨论】:

顺便说一下,为了完整起见,我不得不提一下,delete-Method 还包含用于重置 auto_increment 的 alter table 语句。 【参考方案1】:

实际上,评论中提到的 alter table 语句似乎是问题所在。不确定如何重置 auto_increment 可以清空表,但似乎是这样。

【讨论】:

以上是关于Spring & Hibernate - 使本机查询在与@Transactional 相同的事务中运行的主要内容,如果未能解决你的问题,请参考以下文章

通信链路故障:Hibernate & Spring 应用程序

Spring & Hibernate - 使本机查询在与@Transactional 相同的事务中运行

如何在 Spring & Hibernate 中保存当前用户的信息?

Spring:Spring&Struts2&Hibernate搭建的blog项目

Spring Boot & Hibernate:没有@Type 注释的 NVARCHAR 列类型

Hibernate 4.3.0.Final & Spring Data JPA 1.4.3.RELEASE