我试图对一些持久性代码进行单元测试,并且我遇到了数据库挂起到以前测试中创建的行的问题。我也在使用Hibernate Search,尽管这并没有反映在我在这里分享的代码中。
我使用的是Spring 3.1.x,Hibernate 4.x和HSQLDB 2.3.2
日志
DEBUG - HibernateTransactionManager.doGetTransaction(290) | Found thread-bound Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] orphanRemovals=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] collectionQueuedOps=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] for Hibernate transaction
DEBUG - AbstractPlatformTransactionManager.handleExistingTransaction(470) | Participating in existing transaction
Hibernate: insert into UserRole (userRoleId, label) values (default, ?)
DEBUG - HibernateTransactionManager.doGetTransaction(290) | Found thread-bound Session [SessionImpl(PersistenceContext[entityKeys=[EntityKey[nl.project.model.user.UserRole#1]],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] orphanRemovals=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] collectionQueuedOps=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] for Hibernate transaction
DEBUG - AbstractPlatformTransactionManager.handleExistingTransaction(470) | Participating in existing transaction
Hibernate: insert into UserRole (userRoleId, label) values (default, ?)
***First test****
DEBUG - AbstractPlatformTransactionManager.processRollback(843) | Initiating transaction rollback
DEBUG - HibernateTransactionManager.doRollback(496) | Rolling back Hibernate transaction on Session [SessionImpl(PersistenceContext[entityKeys=[EntityKey[nl.project.model.user.User#1],EntityKey[nl.project.model.user.UserRole#1],EntityKey[nl.project.model.user.UserRole#2], EntityKey[nl.project.model.user.UserRole#3]],collectionKeys=[CollectionKey[nl.project.model.user.User.roles#1]]];ActionQueue[insertions=[] updates=[] deletions=[] orphanRemovals=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] collectionQueuedOps=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])]
DEBUG - HibernateTransactionManager.doBegin(342) | Opened new Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] orphanRemovals=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] collectionQueuedOps=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] for Hibernate transaction
DEBUG - HibernateTransactionManager.doBegin(352) | Preparing JDBC Connection of Hibernate Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] orphanRemovals=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] collectionQueuedOps=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])]
DEBUG - HibernateTransactionManager.doBegin(413) | Exposing Hibernate transaction as JDBC transaction [com.jolbox.bonecp.ConnectionHandle@73d17d67]
DEBUG - HibernateTransactionManager.doGetTransaction(290) | Found thread-bound Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] orphanRemovals=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] collectionQueuedOps=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] for Hibernate transaction
DEBUG - AbstractPlatformTransactionManager.handleExistingTransaction(470) | Participating in existing transaction
DEBUG - HibernateTransactionManager.doGetTransaction(290) | Found thread-bound Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] orphanRemovals=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] collectionQueuedOps=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] for Hibernate transaction
DEBUG - AbstractPlatformTransactionManager.handleExistingTransaction(470) | Participating in existing transaction
DEBUG - HibernateTransactionManager.doGetTransaction(290) | Found thread-bound Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] orphanRemovals=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] collectionQueuedOps=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] for Hibernate transaction
DEBUG - AbstractPlatformTransactionManager.handleExistingTransaction(470) | Participating in existing transaction
Hibernate: select this_.userRoleId as userRole1_92_0_, this_.label as label2_92_0_ from UserRole this_
DEBUG - HibernateTransactionManager.doGetTransaction(290) | Found thread-bound Session [SessionImpl(PersistenceContext[entityKeys=[EntityKey[nl.project.model.user.UserRole#3], EntityKey[nl.project.model.user.UserRole#2], EntityKey[nl.project.model.user.UserRole#1]],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] orphanRemovals=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] collectionQueuedOps=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] for Hibernate transaction
DEBUG - AbstractPlatformTransactionManager.handleExistingTransaction(470) | Participating in existing transaction
Hibernate: insert into UserRole (userRoleId, label) values (default, ?)
WARN - SqlExceptionHelper.logExceptions(144) | SQL Error: -104, SQLState: 23505
ERROR - SqlExceptionHelper.logExceptions(146) | integrity constraint violation: unique constraint or index violation; UK_O0VIK8LBO8UYMR8WUDN5T21QX table: USERROLE
代码
@Entity
@Immutable
@Table
@NaturalIdCache(region=CacheRegion.NATURAL)
@Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE,region=CacheRegion.USER)
public class UserRole implements Serializable{
public static final String ROLE_ANONYMOUS="ROLE_ANONYMOUS";
public static final String ROLE_USER="ROLE_USER";
public static final String ROLE_PROVENDOR="ROLE_PROVENDOR";
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(nullable=false, updatable=false)
private Long id;
@Column(nullable=false,unique=true,updatable=false)
@NaturalId
private String label;
...
}
代码
public class CoreTest extends TestCase {
@Inject
protected SimpleManager<Long> simpleMgr;
public void baseSetup(){
simpleMgr.flush();
simpleMgr.clear();
//after 1st test this contains all created UserRoles
List roles = simpleMgr.getAll(UserRole.class);
UserRole role = new UserRole(UserRole.ROLE_ANONYMOUS);
simpleMgr.save(role);
role = new UserRole(UserRole.ROLE_USER);
simpleMgr.save(role);
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
"classpath:/spring/applicationContext.xml"
"classpath:/spring/applicationContext-transaction.xml"})
public class MyManagerTest extends CoreTest{
@Before
public void methodSetup(){
super.baseSetup();
role = new UserRole(UserRole.ROLE_PROUSER);
simpleMgr.save(role);
simpleMgr.save(userMgr.createUser("marc", "marc@gmail.com"));
simpleMgr.flush();
}
@Test
@Transactional
public void test1(){
...
}
@Test
@Transactional
public void test2(){
....
}
交易管理
<bean id="dataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
<property name="targetDataSource" ref="mainDataSource"/>
</bean>
<bean id="mainDataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}"/>
[...]
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
<property name="hibernateProperties">
<value>
hibernate.connection.driver_class=${jdbc.driverClassName}
hibernate.jdbc.batch_size=30
hibernate.dialect=${hibernate.dialect}
hibernate.connection.autoReconnect=true
hibernate.connection.autoReconnectForPools=true
hibernate.connection.autocommit=false
</value>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
答案 0 :(得分:0)
尝试在测试类上添加@Transactional注释。 http://docs.spring.io/spring/docs/2.0.x/api/org/springframework/transaction/annotation/Transactional.html
答案 1 :(得分:0)
尝试添加事务拦截器:
<beans xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
...
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
答案 2 :(得分:0)
扩展AbstractTransactionalJunit4SpringContextTests或添加@TestExecutionListeners(TransactionalTestExecutionListener.class)。
答案 3 :(得分:0)
所以,我终于通过在BoneCPDatasource上指定defaultAutoCommit = false来实现这一点。 AFAIK对于这种配置来说太低了,因此可能是错误的。但至少它正在发挥作用。