无法在检查异常时回滚事务
Unable to rollback a transaction on a checked exception
尽管我已将 MyServiceImpl
标记为 @Transactional(rollbackFor = IllegalStateException.class)
,但如果抛出 IllegalStateException
,以下服务无法回滚保留 Foo
对象。我还尝试将 upload
方法标记为 @Transactional(rollbackFor = IllegalStateException.class)
,但问题仍然存在,如果发生 IllegalStateException
,我的数据库状态将不一致:
@Service
@Transactional
public class MyServiceImpl implements IMyService{
@Autowired
private IFooService fooService;
@Autowired
private IBarService barService;
@Override
@Transactional(rollbackFor = IllegalStateException.class, propagation = Propagation.REQUIRED)
public void upload(Foo foo, Bar bar) throws IllegalStateException{
try{
fooService.addFoo(foo);//foo object is persisted in the DB whether the upload call would succeed or fail (i.e. throws an IllegalStateException)
if(!check(bar))
throw new IllegalStateException("The object bar is not valid");
barService.addBar();
} catch(Exception e){
e.printStackTrace();
}
}
//This method simply validates the input Bar object
private boolean check(Bar bar){
//source code omitted
}
}
@Service
@Transactional
public class FooServiceImpl implements IFooService{
@Autowired
private IFooDao fooDao;
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addFoo(final Foo foo){
fooDao.addFoo(foo);
}
}
@Service
@Transactional
public class BarServiceImpl implements IBarService{
@Autowired
private IBarDao barDao;
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addBar(final Bar bar){
barDao.addBar(bar);
}
}
public class Foo implements Serializable{
private int id;
//source code omitted
}
public class Bar implements Serializable{
private int id;
private Foo foo;
//source code omitted
}
我的数据源配置:
@Bean(name="dataSource")
public ComboPooledDataSource getDataSource() throws PropertyVetoException{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass(env.getProperty("db.driverClass"));
dataSource.setJdbcUrl(env.getProperty("db.jdbcUrl"));
dataSource.setUser(env.getProperty("db.user"));
dataSource.setPassword(env.getProperty("db.password"));
dataSource.setMaxPoolSize(50);
dataSource.setMinPoolSize(5);
dataSource.setMaxConnectionAge(1800);
dataSource.setMaxIdleTime(1800);
dataSource.setAutoCommitOnClose(false);
dataSource.setInitialPoolSize(5);
return dataSource;
}
请问我该如何解决?
UPDATE:更新了源代码并添加了 try/catch
子句。
看起来 addFoo
在它自己的转换中执行。
你可以用
注释它
@Transactional(propagation = Propagation.REQUIRED)
这样它将在那种情况下使用相同的事务,并在没有@Transactional 注释的情况下从其他地方调用时创建一个新事务。
我花了一段时间才找出回滚失败的原因。感谢 ben75 的回答。事实上,我提供的源代码并不完整。我忘记在 upload
方法中添加 try/catch
子句。尽管 IllegalStateException
被抛出,但这确实阻止了事务被回滚。除此之外,我不需要指定传播级别,因为默认情况下它是 REQUIRED
。
尽管我已将 MyServiceImpl
标记为 @Transactional(rollbackFor = IllegalStateException.class)
,但如果抛出 IllegalStateException
,以下服务无法回滚保留 Foo
对象。我还尝试将 upload
方法标记为 @Transactional(rollbackFor = IllegalStateException.class)
,但问题仍然存在,如果发生 IllegalStateException
,我的数据库状态将不一致:
@Service
@Transactional
public class MyServiceImpl implements IMyService{
@Autowired
private IFooService fooService;
@Autowired
private IBarService barService;
@Override
@Transactional(rollbackFor = IllegalStateException.class, propagation = Propagation.REQUIRED)
public void upload(Foo foo, Bar bar) throws IllegalStateException{
try{
fooService.addFoo(foo);//foo object is persisted in the DB whether the upload call would succeed or fail (i.e. throws an IllegalStateException)
if(!check(bar))
throw new IllegalStateException("The object bar is not valid");
barService.addBar();
} catch(Exception e){
e.printStackTrace();
}
}
//This method simply validates the input Bar object
private boolean check(Bar bar){
//source code omitted
}
}
@Service
@Transactional
public class FooServiceImpl implements IFooService{
@Autowired
private IFooDao fooDao;
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addFoo(final Foo foo){
fooDao.addFoo(foo);
}
}
@Service
@Transactional
public class BarServiceImpl implements IBarService{
@Autowired
private IBarDao barDao;
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addBar(final Bar bar){
barDao.addBar(bar);
}
}
public class Foo implements Serializable{
private int id;
//source code omitted
}
public class Bar implements Serializable{
private int id;
private Foo foo;
//source code omitted
}
我的数据源配置:
@Bean(name="dataSource")
public ComboPooledDataSource getDataSource() throws PropertyVetoException{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass(env.getProperty("db.driverClass"));
dataSource.setJdbcUrl(env.getProperty("db.jdbcUrl"));
dataSource.setUser(env.getProperty("db.user"));
dataSource.setPassword(env.getProperty("db.password"));
dataSource.setMaxPoolSize(50);
dataSource.setMinPoolSize(5);
dataSource.setMaxConnectionAge(1800);
dataSource.setMaxIdleTime(1800);
dataSource.setAutoCommitOnClose(false);
dataSource.setInitialPoolSize(5);
return dataSource;
}
请问我该如何解决?
UPDATE:更新了源代码并添加了 try/catch
子句。
看起来 addFoo
在它自己的转换中执行。
你可以用
注释它@Transactional(propagation = Propagation.REQUIRED)
这样它将在那种情况下使用相同的事务,并在没有@Transactional 注释的情况下从其他地方调用时创建一个新事务。
我花了一段时间才找出回滚失败的原因。感谢 ben75 的回答。事实上,我提供的源代码并不完整。我忘记在 upload
方法中添加 try/catch
子句。尽管 IllegalStateException
被抛出,但这确实阻止了事务被回滚。除此之外,我不需要指定传播级别,因为默认情况下它是 REQUIRED
。