Junit+Hibernate+Spring+H2 :inserts 执行没有错误但是 select 没有返回数据
Posted
技术标签:
【中文标题】Junit+Hibernate+Spring+H2 :inserts 执行没有错误但是 select 没有返回数据【英文标题】:Junit+Hibernate+Spring+H2 :inserts were executed without errors but select returns no data 【发布时间】:2013-01-11 14:39:30 【问题描述】:我正在尝试使用内存数据库 H2 对我的代码中的事务进行 junit 测试。 一切看起来都很好 - 表是从 hbm2ddl 创建的,执行了插入但 select 返回 null。
Junit 在线测试失败:
assertNotNull(artifactManager.getArtifact(id));
整体测试
@Test
@Transactional()
@Rollback(true)
public void failTransactionOnUpdateArtifactStateArtifactVerification() throws IllegalStateException, IOException
//GIVEN
//some initialization already happened
artifactManager.saveArtifact(artifact);
//WHEN
HibernateException exc = Mockito.mock(HibernateException.class);
Mockito.when(historyDao.saveArtifactInHistory(artifact, ver)).thenThrow(exc);
//THEN
//artifact should be present in DB
assertNotNull(artifactManager.getArtifact(id));
assertEquals(artifactManager.getArtifact(id).getState().getType(),StateTypes.SENT);
//and after exception rollback on artifacts Table should be performed and no artifacts should be present in DB
try
stateService.updateArtifactState( ver,artifact);
catch(Exception e)
e.printStackTrace();
//updateArtifact(artifact); should be rolled back and state reverted to SENT
assertEquals(artifactManager.getArtifact(id).getState().getType(),StateTypes.SENT);
控制台日志的相关部分:
2013-01-11 15:02:21,538 INFO [org.hibernate.tool.hbm2ddl.SchemaUpdate] - <schema update complete>
2013-01-11 15:02:21,934 INFO [org.acegisecurity.intercept.AbstractSecurityInterceptor] - <Validated configuration attributes> Hibernate: select artifact0_.Id as Id99_4_, artifact0_.CrosscheckerID as Crossche7_99_4_, artifact0_.CategoryID as CategoryID99_4_, artifact0_.CreationDate as Creation2_99_4_, artifact0_.Description as Descript3_99_4_, artifact0_.FileChecksum as FileChec4_99_4_, artifact0_.ReportID as ReportID99_4_, artifact0_.StateID as StateID99_4_, artifact0_.StateChangeDate as StateCha5_99_4_, artifact0_.Storage as Storage99_4_, user1_.ID as ID86_0_, user1_.Name as Name86_0_, user1_.Surname as Surname86_0_, user1_.username as username86_0_, user1_.jobPositionID as jobPosit5_86_0_, user1_.Email as Email86_0_, user1_.NSNID as NSNID86_0_, user1_.PESEL as PESEL86_0_, user1_.NIP as NIP86_0_, user1_.InProgram as InProgram86_0_, user1_.Employeed as Employeed86_0_, user1_.OutsidePoland as Outside12_86_0_, user1_.Password as Password86_0_, user1_.IncomeCosts as IncomeC14_86_0_, user1_.SupervisorID as Supervi15_86_0_, user1_.Disclosure as Disclosure86_0_, user1_.UserState as UserState86_0_, user1_.FailedLoginAttempts as FailedL18_86_0_, user1_.LastFailedLoginAttempt as LastFai19_86_0_, category2_.ID as ID107_1_, category2_.Name as Name107_1_, category2_."Order" as Order3_107_1_, report3_.ID as ID88_2_, report3_.UserID as UserID88_2_, report3_.StateID as StateID88_2_, report3_.CreationDate as Creation4_88_2_, report3_.StateChangeDate as StateCha5_88_2_, report3_.SupervisorID as Supervis6_88_2_, report3_.AccepterId as AccepterId88_2_, report3_.IncomeCosts as IncomeCo8_88_2_, report3_.AccInProg as AccInProg88_2_, state4_.ID as ID89_3_, state4_.Name as Name89_3_ from Artifacts artifact0_ left outer join Users user1_ on artifact0_.CrosscheckerID=user1_.ID left outer join Categories category2_ on artifact0_.CategoryID=category2_.ID left outer join Reports report3_ on artifact0_.ReportID=report3_.ID left outer join States state4_ on artifact0_.StateID=state4_.ID where artifact0_.Id=?
Hibernate: select max(ID) from Reports
Hibernate: select state0_.ID as ID89_0_, state0_.Name as Name89_0_ from States state0_ where state0_.ID=?
Hibernate: select max(ID) from States
Hibernate: insert into Reports (UserID, StateID, CreationDate, StateChangeDate, SupervisorID, AccepterId, IncomeCosts, AccInProg, ID) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into States (Name, ID) values (?, ?)
Hibernate: insert into Artifacts (Id, CrosscheckerID, CategoryID, CreationDate, Description, FileChecksum, ReportID, StateID, StateChangeDate, Storage) values (null, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: select artifact0_.Id as Id99_5_, artifact0_.CrosscheckerID as Crossche7_99_5_, artifact0_.CategoryID as CategoryID99_5_, artifact0_.CreationDate as Creation2_99_5_, artifact0_.Description as Descript3_99_5_, artifact0_.FileChecksum as FileChec4_99_5_, artifact0_.ReportID as ReportID99_5_, artifact0_.StateID as StateID99_5_, artifact0_.StateChangeDate as StateCha5_99_5_, artifact0_.Storage as Storage99_5_, user1_.ID as ID86_0_, user1_.Name as Name86_0_, user1_.Surname as Surname86_0_, user1_.username as username86_0_, user1_.jobPositionID as jobPosit5_86_0_, user1_.Email as Email86_0_, user1_.NSNID as NSNID86_0_, user1_.PESEL as PESEL86_0_, user1_.NIP as NIP86_0_, user1_.InProgram as InProgram86_0_, user1_.Employeed as Employeed86_0_, user1_.OutsidePoland as Outside12_86_0_, user1_.Password as Password86_0_, user1_.IncomeCosts as IncomeC14_86_0_, user1_.SupervisorID as Supervi15_86_0_, user1_.Disclosure as Disclosure86_0_, user1_.UserState as UserState86_0_, user1_.FailedLoginAttempts as FailedL18_86_0_, user1_.LastFailedLoginAttempt as LastFai19_86_0_, category2_.ID as ID107_1_, category2_.Name as Name107_1_, category2_."Order" as Order3_107_1_, report3_.ID as ID88_2_, report3_.UserID as UserID88_2_, report3_.StateID as StateID88_2_, report3_.CreationDate as Creation4_88_2_, report3_.StateChangeDate as StateCha5_88_2_, report3_.SupervisorID as Supervis6_88_2_, report3_.AccepterId as AccepterId88_2_, report3_.IncomeCosts as IncomeCo8_88_2_, report3_.AccInProg as AccInProg88_2_, user4_.ID as ID86_3_, user4_.Name as Name86_3_, user4_.Surname as Surname86_3_, user4_.username as username86_3_, user4_.jobPositionID as jobPosit5_86_3_, user4_.Email as Email86_3_, user4_.NSNID as NSNID86_3_, user4_.PESEL as PESEL86_3_, user4_.NIP as NIP86_3_, user4_.InProgram as InProgram86_3_, user4_.Employeed as Employeed86_3_, user4_.OutsidePoland as Outside12_86_3_, user4_.Password as Password86_3_, user4_.IncomeCosts as IncomeC14_86_3_, user4_.SupervisorID as Supervi15_86_3_, user4_.Disclosure as Disclosure86_3_, user4_.UserState as UserState86_3_, user4_.FailedLoginAttempts as FailedL18_86_3_, user4_.LastFailedLoginAttempt as LastFai19_86_3_, state5_.ID as ID89_4_, state5_.Name as Name89_4_ from Artifacts artifact0_ left outer join Users user1_ on artifact0_.CrosscheckerID=user1_.ID left outer join Categories category2_ on artifact0_.CategoryID=category2_.ID left outer join Reports report3_ on artifact0_.ReportID=report3_.ID left outer join Users user4_ on report3_.UserID=user4_.ID left outer join States state5_ on artifact0_.StateID=state5_.ID where artifact0_.Id=?
2013-01-11 15:02:22,213 INFO [org.hibernate.impl.SessionFactoryImpl] - <closing>
我的数据库配置如下:
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:mem:taxMemDB;DB_CLOSE_DELAY=-1" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
<bean id="taxSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" >
<property name="AnnotatedClasses">
<list> ...</list>
</property>
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list>
<value>mapping.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.connection.charSet=UTF-8
hibernate.connection.pool_size=15
hibernate.show_sql=true
hibernate.hbm2ddl.auto=update
</value>
</property>
</bean>
<bean id="hibernateTemplate"
class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory">
<ref bean="taxSessionFactory" />
</property>
</bean>
任何线索可能是错的?还是我应该附加更多代码?
--请求的代码 工件管理器:
public Artifact getArtifact(long artifactId)
Artifact artifact = artifactDao.getArtifact(artifactId);
return artifact;
ArtifactDao:
@Override
public Artifact getArtifact(Long id)
Session session = sessionFactory.getCurrentSession();
return (Artifact) session.get(Artifact.class, id);
ArtifactManager.saveArifact:
@Transactional(rollbackFor = Exception.class)
public boolean saveArtifact(Artifact artifact)throws IOException
String checksum = null;
String userPath = null;
checksum = checksumGenerator.generateChecksum(artifact.getFile().getInputStream());
userPath = storageManager.upload(artifact);
artifact.setStoragePath(userPath);
artifact.setFileChecksum(checksum);
if(artifact.getId()!=null)
return artifactDao.mergeArtifact(artifact);
else
return artifactDao.saveOrUpdateArtifact(artifact);
ArifactDao 部分
@Override
public boolean saveOrUpdateArtifact(Artifact artifact)
Session session = sessionFactory.getCurrentSession();
try
session.saveOrUpdate(artifact);
catch (DataAccessException ex)
log.error(ex.getMessage());
return false;
return true;
@Override
public boolean mergeArtifact(Artifact artifact)
Session session = sessionFactory.getCurrentSession();
try
session.merge(artifact);
catch (DataAccessException ex)
log.error(ex.getMessage());
return false;
return true;
【问题讨论】:
能否贴出 artifactManager.getArtifact(id) 的代码 您在日志文件中的插入语句显示正在为一个值插入一个空值。在您获取工件之前设置的 id 是什么?它是一个生成的值。此外,您的模拟看起来也有点可疑,因为他们没有在何时使用匹配项。 我已经添加了请求的代码。插入中的空值也困扰着我,但工件是用 id(10L) 初始化的,即使调试器显示是正确的,但似乎休眠没有看到它..奇怪 【参考方案1】:我认为您的方法 ArtifactManager.getArtifact(id)
正在直接查看数据库,并且由于您的事务尚未提交......它什么也没找到。
注意@Rollback(true)
表示你的事务永远不会被提交。
编辑
根据您的代码,您似乎正在寻找当前会话以查找工件(因此,未提交事务的 OK 事件)。
其他一些对检查有用的代码:
如何在映射中指定工件的 ID? (自动生成还是手动定义?)saveArtifact
方法的代码是什么?
编辑
我发现你的代码有一些烦人的地方:
您正在调用saveArtifact
,但您没有检查返回值。在做任何其他事情之前最好检查一下。类似assertTrue(artifactManager.saveArtifact(artifact)));
通常,在合并实例时,将合并后的实例取回是很有趣的……但在您的 DAO 中,您会忘记它并返回一个布尔值。见merge API,真正有趣的是这个
根据您的 cmets,该工件使用 id=10L 进行初始化。因此,您将调用 session.merge 方法。但是您的工件不应该在会话中,也不应该在数据库中......所以我认为您应该在某处有一些相关的错误日志?没有?给定的实例(即参数)不会与会话关联。
【讨论】:
谢谢,可能是这样,我会用不同的交易填满表格,如果您的提示有效,请告诉您。 在本例中没有错误,但我遵循了您的第一个建议并在单独的事务中初始化了数据库,这有帮助,现在的问题是休眠在预期异常后不执行回滚(不能回滚休眠事务;事务未开始)以上是关于Junit+Hibernate+Spring+H2 :inserts 执行没有错误但是 select 没有返回数据的主要内容,如果未能解决你的问题,请参考以下文章
Spring Hibernate H2 Junit 测试 - 如何在启动时加载模式
Spring4 JUnit 测试:将 SQL 加载到 H2 数据库
使用 h2 进行 Spring Junit 测试 - 找不到表