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项目