我试图在一个事务中插入两个记录到我的数据库中。第二次插入失败,但是在回滚中第一次插入没有被删除:
@Resource
private WebMessageRep rep; //<-- extends JpaRepository
@Transactional
public void test() {
WebMessage wm = new WebMessage(.valid params.);
wm = rep.save(wm);//<-- save is crud save which is transactional by default
WebMessage wm2 = new WebMessage(.invalid params.);
rep.save(wm2);
}
(我还尝试将save方法替换为:jpaContext.getEntityManagerByManagedType(WebMessage.class)。坚持(wm);因此,我不使用crud保存,但问题仍然存在)
我启用了事务日志以查看发生了什么,我发现:
在调用test()之前,会创建一个新事务,因为@transactional Annotation:
Creating new transaction with name [com..data.webmessage.WebMessageServiceImpl.test]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
Opened new EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for JPA transaction
调用first save,它会看到第一个事务:
Found thread-bound EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for JPA transaction
第二次保存也会看到第一个事务:
Found thread-bound EntityManager [SessionImpl(PersistenceContext[entityKeys=[EntityKey[com..shared.WebMessage#107]],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=1} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for JPA transaction
2017-02-22 14:07:22,000 [ main] DEBUG orm.jpa.JpaTransactionManager - Participating in existing transaction
退出test()时,提交完成:
Committing JPA transaction on EntityManager [SessionImpl(PersistenceContext[entityKeys=[EntityKey[com..shared.WebMessage#108], EntityKey[com..shared.WebMessage#107]],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=2} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])]
它失败了:
Column 'text' cannot be null
HHH000010: On release of batch it still contained JDBC statements
HHH000346: Error during managed flush [org.hibernate.exception.ConstraintViolationException: could not execute statement]
Initiating transaction rollback after commit exception
回滚:
Rolling back JPA transaction on EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])]
奇怪的是第一个插入的记录还在我的数据库(mysql)中。
不确定它是否意味着什么,但在提交时我们有:插入=可执行列表{大小=2},但在回滚时是:插入=可执行列表{大小=0}
有人知道为什么它不回滚第一次插入吗?
我的事务配置非常简单:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
启动我的调试器显示,当尝试回滚时,我的事务不再活跃。让我解释一下:
[JpaTransactionManager.java]
@Override
protected void doRollback(DefaultTransactionStatus status) {
JpaTransactionObject txObject = (JpaTransactionObject) status.getTransaction();
if (status.isDebug()) {
logger.debug("Rolling back JPA transaction on EntityManager [" +
txObject.getEntityManagerHolder().getEntityManager() + "]");
}
try {
EntityTransaction tx = txObject.getEntityManagerHolder().getEntityManager().getTransaction();
if (tx.isActive()) {
tx.rollback();
}
}
catch (PersistenceException ex) {
throw new TransactionSystemException("Could not roll back JPA transaction", ex);
}
finally {
if (!txObject.isNewEntityManagerHolder()) {
// Clear all pending inserts/updates/deletes in the EntityManager.
// Necessary for pre-bound EntityManagers, to avoid inconsistent state.
txObject.getEntityManagerHolder().getEntityManager().clear();
}
}
}
上面代码中的tx.isActive()返回false,这意味着不执行回滚。
现在最大的问题是为什么我的交易不再活跃?
看起来问题出在mysql上,Spring data jpa生成的表属于myisam类型。
当使用某些类型的交易时,myisam似乎变得不稳定。
我将我的表转换为innodb,现在它可以工作了:当事务失败并回滚事务时,所有插入的行都会被删除。当表的类型为myisam时,不会发生这种情况。
在服务中定义了一个事务性函数,并从一个调度任务调用它,在这个函数中,对同一对象进行了两轮插入,在第二轮插入过程中,由于重复键的存在,会引发异常。我已经将事务注释配置为针对抛出的异常进行回滚,并且打开了log4j springframework日志,从日志中我可以看到事务管理器正在对回滚进行一些操作,例如确定是否对抛出的异常进行回滚,但是我看不到任何正在进行数据库删除操作的日志,并且检查数据库显示回
我们为JPA配置了Spring数据。服务事务方法不会因错误而回滚(例如,DB ConstraintViolationException)。 我能找到的最接近的是这个(事务不回滚)Spring-data、JTA、JPA、Wildfly10但是我们没有任何XML配置,我们所有的配置都是基于Java的。 本质上,服务方法如下所示:不捕获错误,抛出所有内容。
情景故事时间: 我“继承”了一个程序,一个用于访问数据库的相当简单的webservice。该程序在某个地方有一个缺陷:它试图更新一个没有更新授权的表。该程序只具有更新数据库队列的权限(Oracle),以保存谁访问了什么信息。这是不受欢迎的行为,现在我纠正了它。注意:这与这个问题本身无关,它只是导致我提出这个问题的原因。 该程序使用Spring+Hibernate来管理和访问数据和事务。 因为程序的
我试图编写一个spring-cloud-stream函数(spring-starter-parent 2.5.3,java 11,spring-cloud-version 2020.0.3),该函数同时具有Kafka和Postgres事务。每当使用的消息以字符串“fail”开始时,该函数将引发一个模拟错误,我希望这将导致数据库事务回滚,然后导致kafka事务回滚。(我知道Kafka交易不是XA,这
我有一个类,它有一个方法,该方法调用另一个服务上的另一个方法。大概是这样的: 我预计一个实体将被插入,但是如果任何嵌套事务抛出异常插入将拒绝,即使这个异常也是在处理的。 我可以用注释。但它会胜过表演。
我们有一个Spring事务回滚问题,其中回滚似乎不起作用 在用注释的服务层方法中,我调用三个不同的类来插入3条记录 中间插入从第四个表执行get以填充描述字段,但此get失败。我希望第一次插入会回滚,但它似乎没有发生 几点: 获取方法抛出运行时异常 我们使用和中定义的。Bean是在中创建的,它被导入到 在层 中没有 注释 我们已经使用了