Reputation: 3563
i'm trying to run some test cases, but when I try to store one object in the ddbb, there is no insert at all.
First, the test is declared with a @Transactional. So all the queries and operations to the ddbb will be in the same transaction. The part of the code where I get errors is:
public Concept storeConcept(Concept concept) throws DataAccessLayerException {
if(concept!=null && concept.getUri()!=null){
super.saveOrUpdate(concept);
concept = this.findByID(concept.getUri());
return concept;
}
return null;
}
At this point, I can not see any kind of insert in the log of my ddbb (using hsql).
super
: the class where this method is extends AbstractHibernateDAOSupport
The problem comes when I try to find the object stored:
ServiceExecutionException: 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 net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:692)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:625)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:692)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:625)
at com.playence.platform.services.localImpl.AnnotationsServiceImpl$$EnhancerByCGLIB$$d2c706a9.createAnnotation(<generated>)
at com.playence.app.mediamanagementTest.TestMediaObjectService.testGetAnnotations(TestMediaObjectService.java:115)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException: 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.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:675)
at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:339)
at com.app.platform.dao.ConceptDao.findByID(ConceptDao.java:110)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:692)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:625)
... 48 more
Because it is not stored. But when I debug this method, even I'm getting the same error, but the process can continue and the method is able to return the object stored. Maybe that concept is somewhere in another session or in hibernate memory, but I can not really understand this problem.
Thanks in advance
EDIT transaction config
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<aop:aspectj-autoproxy proxy-target-class="true"/><!-- Se puede poner tb a nivel de bean -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="serviceOperation"
expression="execution(* com.app.daoTests.**.*(..)) " />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation" />
</aop:config>
EDIT
I have aswell this error:
9898 [main] ERROR org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
It's very common error, and I have been reading something in other threads, but still can not find solution
Upvotes: 0
Views: 4105
Reputation: 3563
After a while, I came back to this problem. I have realized, that the problem was not related with the store method itself. In my test method I had something like:
@Test
public void testCreateAnnotation() throws Exception {
//Store the mediaObject related with the annotations to be created
mediObjectService.storeMediaObject(MockGenericMediaObjectDataPool.GENERIC_MEDIA_OBJECT1);
Assert.assertNotNull(geMO.getId());
//Store annotation
geAnno.setRelatedMediaObjectId(geMO.getId());
geAnno.setMediaObjectInternalURI(geMO.getInternalURI());
annotationService.createAnnotation(MockGenericAnnotationDataPool.TEST_ANNOTATION1);
}
These were two different calls to two different DAO, two different store services to two different tables. As you can see, in the same method. Here is the problem, these two calls must be in two different @Test
methods.
@Test
public void testCreateAnnotation() throws Exception {
//Store the mediaObject related with the annotations to be created
mediObjectService.storeMediaObject(MockGenericMediaObjectDataPool.GENERIC_MEDIA_OBJECT1);
// annotationService.createAnnotation(MockGenericAnnotationDataPool.TEST_ANNOTATION1);
}
@Test
public void testUpdateAnnotation() throws Exception {
Assert.assertNotNull(annotationService);
//Store the mediaObject related with the annotations to be created
// mediObjectService.storeMediaObject(MockGenericMediaObjectDataPool.GENERIC_MEDIA_OBJECT1);
GenericAnnotation geOriginalAnnotation = annotationService.createAnnotation(MockGenericAnnotationDataPool.TEST_ANNOTATION1);
annotationService.updateAnnotation(geOriginalAnnotation);
}
If somebody could explain me the reason of this behavior, I would be really grateful!!
Thanks for all your responses
Upvotes: 0
Reputation: 21000
saveOrUpdate will not insert records if the id has been set, which is what I think is happening in your case. Hibernate decides between an insert or an update based on the value of the id field - if it is not set and ids are being auto generated it will perform an insert otherwise it will update.
In your case it looks like uri is the id - auto generation is turned off. The Concept object that you are saving is new - no row exists in the DB. saveOrUpdate is trying to update a row and failing.
You should use the merge method instead.
The following info from hibernate documentation should help in understanding the difference.
saveOrUpdate() does the following:
and merge() is very different:
Upvotes: 1
Reputation: 15219
Could be because your bean has the id declared as being auto-generated (auto-incremented) and you're passing a new bean instance to the saveOrUpdate method where you've actually set that id manually. This will make Hibernate think that infact you're not passing a new bean, but that you're trying to update the existing one (because he sees a value present for an auto-generated id). So instead of inserting it, he tries to update it (where id=whatever
) and it fails to find it in the database.
Try to either:
declare the id as autogenerated/autoincremented AND make sure you don't manually set it when you pass a new instance of your bean to the saveOrUpdate method
declare the id as non-autogenerated (i.e. don't specify any auto-generation config for it) AND set it manually when saving a new bean.
try using save(...)
and merge(...)
methods rather then saveOrUpdate(...)
Upvotes: 0