Scope of @Transactional
For example, I have a code something like this
@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
}
}
I am getting the following in couple of instances with the above logic. I don't get an error in local machine. My question is if updateUserDetails() will commit the transaction and when updateFewOtherDetails() is executed, since the transaction is committed, is it throwing the exception ? I doubt if that is creating the problem since where are annotating it with @Transactional (propogation= 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)
java spring hibernate jpa
add a comment |
For example, I have a code something like this
@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
}
}
I am getting the following in couple of instances with the above logic. I don't get an error in local machine. My question is if updateUserDetails() will commit the transaction and when updateFewOtherDetails() is executed, since the transaction is committed, is it throwing the exception ? I doubt if that is creating the problem since where are annotating it with @Transactional (propogation= 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)
java spring hibernate jpa
In the comments below you note that By the way, updateUserDetails() is in codeForTest class but it a private method. which is completely different from the code you have posted. Maybe if you asked a coherent question you might get an answer.
– Alan Hay
Nov 20 '18 at 8:37
add a comment |
For example, I have a code something like this
@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
}
}
I am getting the following in couple of instances with the above logic. I don't get an error in local machine. My question is if updateUserDetails() will commit the transaction and when updateFewOtherDetails() is executed, since the transaction is committed, is it throwing the exception ? I doubt if that is creating the problem since where are annotating it with @Transactional (propogation= 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)
java spring hibernate jpa
For example, I have a code something like this
@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
}
}
I am getting the following in couple of instances with the above logic. I don't get an error in local machine. My question is if updateUserDetails() will commit the transaction and when updateFewOtherDetails() is executed, since the transaction is committed, is it throwing the exception ? I doubt if that is creating the problem since where are annotating it with @Transactional (propogation= 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)
java spring hibernate jpa
java spring hibernate jpa
edited Nov 19 '18 at 16:29


Karol Dowbecki
17k82850
17k82850
asked Nov 19 '18 at 16:09
srinivas vishnu
142
142
In the comments below you note that By the way, updateUserDetails() is in codeForTest class but it a private method. which is completely different from the code you have posted. Maybe if you asked a coherent question you might get an answer.
– Alan Hay
Nov 20 '18 at 8:37
add a comment |
In the comments below you note that By the way, updateUserDetails() is in codeForTest class but it a private method. which is completely different from the code you have posted. Maybe if you asked a coherent question you might get an answer.
– Alan Hay
Nov 20 '18 at 8:37
In the comments below you note that By the way, updateUserDetails() is in codeForTest class but it a private method. which is completely different from the code you have posted. Maybe if you asked a coherent question you might get an answer.
– Alan Hay
Nov 20 '18 at 8:37
In the comments below you note that By the way, updateUserDetails() is in codeForTest class but it a private method. which is completely different from the code you have posted. Maybe if you asked a coherent question you might get an answer.
– Alan Hay
Nov 20 '18 at 8:37
add a comment |
2 Answers
2
active
oldest
votes
You are using JPA (Hibernate) with optimistic locking. The actual exception:
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
means that while your transaction was running another transaction updated the same rows, Hibernate detected their stale state and rolled back current transaction to avoid data consistency problems. This can happen with optimistic locking on a contended resource, but it's not bad because due to rollback the data is still consistent in the database.
There are few ways you can resolve this:
- Retry the logic that caused
ObjectOptimisticLockingFailureException
and hope that next transaction won't be contended. - Relax transaction boundaries to perform a few smaller and faster transaction
- Queue updates in application logic
I am very sure that no other thread is doing that. I doubt if updateUserDetails is that other transaction since it has got its own @Transactional and I am sending the that same User object to both the methods. Also, it is a highly consistent error.
– srinivas vishnu
Nov 19 '18 at 16:22
@srinivasvishnu currently your code doesn't even compile. Perhaps if you could provide more complete example one could analyze it better.
– Karol Dowbecki
Nov 19 '18 at 16:30
add a comment |
Both the methods will be executed in bounds of single transaction, once they both marked @Transactional
.
user
object was loaded in bounds of different transaction or taken from cache, in a case .finduserById()
uses the one.
Make sure you've marked @Transactional
second .updateFewOtherDetails()
method too.
With propagation REQUIRED
the transaction won't commit until the end of caller sequence.
Do you mean updateUserDetails() ? I already have an @Transactional on updateFewOtherDetails(). By the way, updateUserDetails() is in codeForTest class but it a private method. Will that make a difference ?
– srinivas vishnu
Nov 19 '18 at 16:37
@srinivasvishnu, yes, it will. Since Spring transactions are AOP based, the components are runtime proxies. It means, your methods have to be public and located in different Spring beans in relation to caller. Cross-member calls are not allowed with default configuration.
– WildDev
Nov 19 '18 at 16:44
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53378609%2fscope-of-transactional%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
You are using JPA (Hibernate) with optimistic locking. The actual exception:
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
means that while your transaction was running another transaction updated the same rows, Hibernate detected their stale state and rolled back current transaction to avoid data consistency problems. This can happen with optimistic locking on a contended resource, but it's not bad because due to rollback the data is still consistent in the database.
There are few ways you can resolve this:
- Retry the logic that caused
ObjectOptimisticLockingFailureException
and hope that next transaction won't be contended. - Relax transaction boundaries to perform a few smaller and faster transaction
- Queue updates in application logic
I am very sure that no other thread is doing that. I doubt if updateUserDetails is that other transaction since it has got its own @Transactional and I am sending the that same User object to both the methods. Also, it is a highly consistent error.
– srinivas vishnu
Nov 19 '18 at 16:22
@srinivasvishnu currently your code doesn't even compile. Perhaps if you could provide more complete example one could analyze it better.
– Karol Dowbecki
Nov 19 '18 at 16:30
add a comment |
You are using JPA (Hibernate) with optimistic locking. The actual exception:
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
means that while your transaction was running another transaction updated the same rows, Hibernate detected their stale state and rolled back current transaction to avoid data consistency problems. This can happen with optimistic locking on a contended resource, but it's not bad because due to rollback the data is still consistent in the database.
There are few ways you can resolve this:
- Retry the logic that caused
ObjectOptimisticLockingFailureException
and hope that next transaction won't be contended. - Relax transaction boundaries to perform a few smaller and faster transaction
- Queue updates in application logic
I am very sure that no other thread is doing that. I doubt if updateUserDetails is that other transaction since it has got its own @Transactional and I am sending the that same User object to both the methods. Also, it is a highly consistent error.
– srinivas vishnu
Nov 19 '18 at 16:22
@srinivasvishnu currently your code doesn't even compile. Perhaps if you could provide more complete example one could analyze it better.
– Karol Dowbecki
Nov 19 '18 at 16:30
add a comment |
You are using JPA (Hibernate) with optimistic locking. The actual exception:
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
means that while your transaction was running another transaction updated the same rows, Hibernate detected their stale state and rolled back current transaction to avoid data consistency problems. This can happen with optimistic locking on a contended resource, but it's not bad because due to rollback the data is still consistent in the database.
There are few ways you can resolve this:
- Retry the logic that caused
ObjectOptimisticLockingFailureException
and hope that next transaction won't be contended. - Relax transaction boundaries to perform a few smaller and faster transaction
- Queue updates in application logic
You are using JPA (Hibernate) with optimistic locking. The actual exception:
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
means that while your transaction was running another transaction updated the same rows, Hibernate detected their stale state and rolled back current transaction to avoid data consistency problems. This can happen with optimistic locking on a contended resource, but it's not bad because due to rollback the data is still consistent in the database.
There are few ways you can resolve this:
- Retry the logic that caused
ObjectOptimisticLockingFailureException
and hope that next transaction won't be contended. - Relax transaction boundaries to perform a few smaller and faster transaction
- Queue updates in application logic
answered Nov 19 '18 at 16:15


Karol Dowbecki
17k82850
17k82850
I am very sure that no other thread is doing that. I doubt if updateUserDetails is that other transaction since it has got its own @Transactional and I am sending the that same User object to both the methods. Also, it is a highly consistent error.
– srinivas vishnu
Nov 19 '18 at 16:22
@srinivasvishnu currently your code doesn't even compile. Perhaps if you could provide more complete example one could analyze it better.
– Karol Dowbecki
Nov 19 '18 at 16:30
add a comment |
I am very sure that no other thread is doing that. I doubt if updateUserDetails is that other transaction since it has got its own @Transactional and I am sending the that same User object to both the methods. Also, it is a highly consistent error.
– srinivas vishnu
Nov 19 '18 at 16:22
@srinivasvishnu currently your code doesn't even compile. Perhaps if you could provide more complete example one could analyze it better.
– Karol Dowbecki
Nov 19 '18 at 16:30
I am very sure that no other thread is doing that. I doubt if updateUserDetails is that other transaction since it has got its own @Transactional and I am sending the that same User object to both the methods. Also, it is a highly consistent error.
– srinivas vishnu
Nov 19 '18 at 16:22
I am very sure that no other thread is doing that. I doubt if updateUserDetails is that other transaction since it has got its own @Transactional and I am sending the that same User object to both the methods. Also, it is a highly consistent error.
– srinivas vishnu
Nov 19 '18 at 16:22
@srinivasvishnu currently your code doesn't even compile. Perhaps if you could provide more complete example one could analyze it better.
– Karol Dowbecki
Nov 19 '18 at 16:30
@srinivasvishnu currently your code doesn't even compile. Perhaps if you could provide more complete example one could analyze it better.
– Karol Dowbecki
Nov 19 '18 at 16:30
add a comment |
Both the methods will be executed in bounds of single transaction, once they both marked @Transactional
.
user
object was loaded in bounds of different transaction or taken from cache, in a case .finduserById()
uses the one.
Make sure you've marked @Transactional
second .updateFewOtherDetails()
method too.
With propagation REQUIRED
the transaction won't commit until the end of caller sequence.
Do you mean updateUserDetails() ? I already have an @Transactional on updateFewOtherDetails(). By the way, updateUserDetails() is in codeForTest class but it a private method. Will that make a difference ?
– srinivas vishnu
Nov 19 '18 at 16:37
@srinivasvishnu, yes, it will. Since Spring transactions are AOP based, the components are runtime proxies. It means, your methods have to be public and located in different Spring beans in relation to caller. Cross-member calls are not allowed with default configuration.
– WildDev
Nov 19 '18 at 16:44
add a comment |
Both the methods will be executed in bounds of single transaction, once they both marked @Transactional
.
user
object was loaded in bounds of different transaction or taken from cache, in a case .finduserById()
uses the one.
Make sure you've marked @Transactional
second .updateFewOtherDetails()
method too.
With propagation REQUIRED
the transaction won't commit until the end of caller sequence.
Do you mean updateUserDetails() ? I already have an @Transactional on updateFewOtherDetails(). By the way, updateUserDetails() is in codeForTest class but it a private method. Will that make a difference ?
– srinivas vishnu
Nov 19 '18 at 16:37
@srinivasvishnu, yes, it will. Since Spring transactions are AOP based, the components are runtime proxies. It means, your methods have to be public and located in different Spring beans in relation to caller. Cross-member calls are not allowed with default configuration.
– WildDev
Nov 19 '18 at 16:44
add a comment |
Both the methods will be executed in bounds of single transaction, once they both marked @Transactional
.
user
object was loaded in bounds of different transaction or taken from cache, in a case .finduserById()
uses the one.
Make sure you've marked @Transactional
second .updateFewOtherDetails()
method too.
With propagation REQUIRED
the transaction won't commit until the end of caller sequence.
Both the methods will be executed in bounds of single transaction, once they both marked @Transactional
.
user
object was loaded in bounds of different transaction or taken from cache, in a case .finduserById()
uses the one.
Make sure you've marked @Transactional
second .updateFewOtherDetails()
method too.
With propagation REQUIRED
the transaction won't commit until the end of caller sequence.
answered Nov 19 '18 at 16:27


WildDev
1,07731949
1,07731949
Do you mean updateUserDetails() ? I already have an @Transactional on updateFewOtherDetails(). By the way, updateUserDetails() is in codeForTest class but it a private method. Will that make a difference ?
– srinivas vishnu
Nov 19 '18 at 16:37
@srinivasvishnu, yes, it will. Since Spring transactions are AOP based, the components are runtime proxies. It means, your methods have to be public and located in different Spring beans in relation to caller. Cross-member calls are not allowed with default configuration.
– WildDev
Nov 19 '18 at 16:44
add a comment |
Do you mean updateUserDetails() ? I already have an @Transactional on updateFewOtherDetails(). By the way, updateUserDetails() is in codeForTest class but it a private method. Will that make a difference ?
– srinivas vishnu
Nov 19 '18 at 16:37
@srinivasvishnu, yes, it will. Since Spring transactions are AOP based, the components are runtime proxies. It means, your methods have to be public and located in different Spring beans in relation to caller. Cross-member calls are not allowed with default configuration.
– WildDev
Nov 19 '18 at 16:44
Do you mean updateUserDetails() ? I already have an @Transactional on updateFewOtherDetails(). By the way, updateUserDetails() is in codeForTest class but it a private method. Will that make a difference ?
– srinivas vishnu
Nov 19 '18 at 16:37
Do you mean updateUserDetails() ? I already have an @Transactional on updateFewOtherDetails(). By the way, updateUserDetails() is in codeForTest class but it a private method. Will that make a difference ?
– srinivas vishnu
Nov 19 '18 at 16:37
@srinivasvishnu, yes, it will. Since Spring transactions are AOP based, the components are runtime proxies. It means, your methods have to be public and located in different Spring beans in relation to caller. Cross-member calls are not allowed with default configuration.
– WildDev
Nov 19 '18 at 16:44
@srinivasvishnu, yes, it will. Since Spring transactions are AOP based, the components are runtime proxies. It means, your methods have to be public and located in different Spring beans in relation to caller. Cross-member calls are not allowed with default configuration.
– WildDev
Nov 19 '18 at 16:44
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53378609%2fscope-of-transactional%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
In the comments below you note that By the way, updateUserDetails() is in codeForTest class but it a private method. which is completely different from the code you have posted. Maybe if you asked a coherent question you might get an answer.
– Alan Hay
Nov 20 '18 at 8:37