[英]Scope of @Transactional
例如,我有这样的代码
@Transactional(propogation=PROPOGATION.REQUIRED)
public class codeForTest {
public void doSomethins(){
User user = userRepository.finduserById(userId);
updateUserDetails(user);
updateFewOtherDetails(user);
}
}
public class DifferentClass{
@Transactional(propogation=PROPOGATION.REQUIRED)
updateUserDetails() {
//UPDATES user object
}
}
在上述几种情况下,我得到了以下几个例子。 我在本地计算机上没有收到错误。 我的问题是,如果updateUserDetails()将提交事务,并且在执行updateFewOtherDetails()时,由于提交了事务,是否会引发异常? 我怀疑这是否在造成问题,因为在哪里用@Transactional注释(传播= PROPOGATION.REQUIRED)
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:81)
at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:73)
at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.checkRowCounts(BatchingBatch.java:151)
at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.performExecution(BatchingBatch.java:128)
at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.doExecuteBatch(BatchingBatch.java:111)
at org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl.execute(AbstractBatchImpl.java:163)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.executeBatch(JdbcCoordinatorImpl.java:226)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:482)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:349)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1222)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:77)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517)
... 130 common frames omitted
Wrapped by: org.springframework.orm.ObjectOptimisticLockingFailureException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; nested exception is org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:297)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:221)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:521)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:765)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:734)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:518)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:292)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy1125.createUserSession(Unknown Source)
您正在使用具有乐观锁定功能的JPA(休眠)。 实际的例外:
org.springframework.orm.ObjectOptimisticLockingFailureException:批处理更新从更新[0]返回了意外的行数; 实际行数:0; 预期:1; 嵌套的异常是org.hibernate.StaleStateException:批处理更新从更新[0]返回了意外的行数; 实际行数:0; 预期:1
意味着当您的事务正在运行时,另一个事务更新了相同的行,Hibernate检测到它们的陈旧状态并回滚当前事务以避免数据一致性问题。 乐观地锁定竞争的资源可能会发生这种情况,但这并不坏,因为由于回滚,数据库中的数据仍然保持一致。
有几种方法可以解决此问题:
ObjectOptimisticLockingFailureException
的逻辑,并希望不会竞争下一个事务。 两种方法都标记为@Transactional
,将在单个事务的边界内执行。
如果.finduserById()
使用一个对象, .finduserById()
user
对象加载到不同事务的边界中或从缓存中.finduserById()
。
确保您也已标记@Transactional
第二个.updateFewOtherDetails()
方法。
在REQUIRED
传播的情况下,直到调用者序列结束,事务才提交。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.