这是我的问题:
我正在Java EE/Spring/Hibernate应用程序上运行批处理.这个批次调用了method1.这个方法调用一个method2可以抛出的UserException(一个类扩展RuntimeException).这是它的样子:
@Transactional
public class BatchService implements IBatchService {
@Transactional(propagation=Propagation.REQUIRES_NEW)
public User method2(User user) {
// Processing, which can throw a RuntimeException
}
public void method1() {
// ...
try {
this.method2(user);
} catch (UserException e) {
// ...
}
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
在执行继续时捕获异常,但在method1事务关闭结束时抛出RollbackException.
这是堆栈跟踪:
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:476)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
at …Run Code Online (Sandbox Code Playgroud) 一切都很棒,直到遇到我确实需要捕捉异常的地方.当我放置
jdbcTemplate.query(something...)
Run Code Online (Sandbox Code Playgroud)
在
try{}
Run Code Online (Sandbox Code Playgroud)
块我得到:
Unreachable catch block for SQLException. This exception is never thrown from the try statement body.
Run Code Online (Sandbox Code Playgroud)
在这种情况下我该怎么办?
try{
personIdReturnedByDb = jdbcTemplate.queryForInt(sql, p.getEmail(),
p.getName(), p.getSurname(), encPw, dateSql);
}
catch(SQLException sa){
}
Run Code Online (Sandbox Code Playgroud)
谢谢,
我想使用spring测试框架测试hibernate session的save()方法.@Test方法是:
@Test
@Transactional
public void testSave() {
User expected = createUser();
getGenericDao().currentSession().save(expected);
User actual = getUser(generatedId);
assertUsersEqual(expected,actual);
}
Run Code Online (Sandbox Code Playgroud)
我想将用户刷新到数据库中.我想让我的用户在这个方法之后进入数据库
getGenericDao().currentSession().save(expected);
Run Code Online (Sandbox Code Playgroud)
然后我想使用spring数据框架转到数据库,并通过下一行获取此保存的用户:
User actual = getUser(generatedId);
Run Code Online (Sandbox Code Playgroud)
我尝试使用hibernate flush方法,如:
currentSession().setFlushMode(MANUAL);
//do saving here
currentSession().flush();
Run Code Online (Sandbox Code Playgroud)
它不会将我的用户刷新到数据库中!但是,如果我没有使用@Transactional spring注释并将我的用户保存在编程弹簧事务中,那么我实现了我想要的.不幸的是,由于没有spring @Transactional,因此保存到db的用户不会回滚.因此,我的测试方法会更改后续测试方法的db和行为.
所以我需要将我的用户刷新到db里面的测试方法(不是在最后),并在测试方法结束时回滚所有对db的更改.
UPDATE建议准备方法如下:
@Transactional
public void doSave(User user){
getGenericDao().currentSession().save(user);
}
Run Code Online (Sandbox Code Playgroud)
并且在testSave中调用doSave什么都不做.执行此方法后,我仍然没有db中的用户.我设置断点并从命令行检查我的数据库.
更新非常感谢您的回复.问题是方法flush()不会将我的用户放入数据库.我尝试了Isolation.READ_UNCOMMITTED并且它没有将我的用户放入数据库.我可以实现我想要的,但前提是我在@Test方法上关闭spring事务并在程序化事务中保存.然后@Test方法不回滚,为后续的@Test方法留下保存的用户.这里保存用户的@Test方法不像删除用户的@Test方法那样危险,因为它没有回滚.因此必须对@Test方法提供Spring事务支持,我无法将我的用户(或删除)放入db.实际上,只有在@Test方法结束并且@Test方法的事务被调用后,才会将用户放入(或删除)到db中.所以我想在@Test方法的中间将我的用户保存到db中,并在@Test方法结束时回滚它
谢谢!
java hibernate spring-test hibernate-session spring-transactions
我使用Spring和JDBC,发现它是自动提交.
如何配置在spring-servlet.xml中将其关闭?
这是我目前的配置:
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.databaseurl}" p:username="${jdbc.username}"
p:password="${jdbc.password}" />
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
Run Code Online (Sandbox Code Playgroud) java ×4
hibernate ×2
jdbc ×2
spring ×2
rollback ×1
spring-jdbc ×1
spring-test ×1
transactions ×1