我试图运行一些测试用例,但是当我尝试在ddbb中存储一个对象时,根本就没有插入。
首先,使用@Transactional声明测试。因此,ddbb的所有查询和操作都将在同一个事务中。我得到错误的代码部分是:
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;
}
此时,我在ddbb的日志中看不到任何类型的插入(使用hsql)。
super
:此方法为extends AbstractHibernateDAOSupport
当我尝试找到存储的对象时出现问题:
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
因为它没有存储。但是当我调试这个方法时,即使我得到相同的错误,但是该过程可以继续并且该方法能够返回存储的对象。 也许这个概念在另一个会话或休眠内存中,但我无法真正理解这个问题。
提前致谢
编辑交易配置
<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>
修改
我还有这个错误:
9898 [main] ERROR org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
这是非常常见的错误,我一直在阅读其他帖子中的内容,但仍无法找到解决方案
答案 0 :(得分:1)
在你的情况下,看起来uri是id - 自动生成已关闭。您要保存的Concept对象是新的 - DB中不存在任何行。 saveOrUpdate正在尝试更新行并失败。
您应该使用合并方法。
来自hibernate documentation的以下信息应该有助于理解差异。
saveOrUpdate()执行以下操作:
和merge()非常不同:
答案 1 :(得分:0)
可能是因为你的bean声明为自动生成的id(自动递增),并且你将 new bean实例传递给saveOrUpdate方法,你实际上已经设置了该id手动。这将使Hibernate认为你实际上并没有传递新的bean,而是你正在尝试更新现有的bean(因为他看到了一个自动生成的id存在的值)。因此,他试图更新它(where id=whatever
)而不是插入它,而无法在数据库中找到它。
尝试:
将id声明为autogenerated / autoincremented,并确保在将bean的新实例传递给saveOrUpdate方法时不要手动设置它
将id声明为非自动生成(即不为其指定任何自动生成配置)并在保存新bean时手动设置它。
尝试使用save(...)
和merge(...)
方法,而不是saveOrUpdate(...)
答案 2 :(得分:0)
过了一会儿,我回到了这个问题。我已经意识到,问题与存储方法本身无关。在我的测试方法中,我有类似的东西:
@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);
}
这是对两个不同DAO的两个不同调用,两个不同的存储服务到两个不同的表。如您所见,采用相同的方法。这是问题,这两个调用必须使用两种不同的@Test
方法。
@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);
}
如果有人能解释我这种行为的原因,我会非常感激!! 感谢您的所有回复