我的问题与事务和异常有关
要求:
我有10条记录要插入数据库表中。在插入每条记录之后,我将数据插入到另一个表中。因此,如果插入第二张表失败,我想回滚该记录。
例如
假设一次处理10人的现金转移(从一个帐户到一个帐户)。
伪代码:
------------- EJB方法的开始
for(int i = 0; i < TransferRecords.length; i++)
{
try
{
//Deduct cash from TransferRecord.accountFrom --- Includes use of Hibernate Session
//Add cash in TransferRecord.accountTo -- Includes use of Hibernate Session
} catch(AppException exception)
{
//Rollback the transaction only for this particular transfer (i)
// But here when I go for next record it says session is closed
}
}
--------- EJB方法的结尾
在这里,AppException是使用@ApplicaitonException(rollback = true)注释创建的。
我们想要的功能是:即使TransferRecord的事务失败(例如2),我也希望将数据提交给记录0,记录1,记录3,记录4(等等……而不是记录2)
但是这里的问题是:当TransferRecord 2失败并且当我移至TransferRecord 3时,出现“会话关闭”错误。
我的怀疑是:
1.这是正确的方法吗?还是应该在EJB之外运行for循环(对于每个TransferRecord)
2.如何确定会话未关闭但事务已回滚(仅适用于特定失败事务的事务)
先感谢您。
我正在使用EJB3,Hibernate 3.x,Jboss 4.2.x,并且正在使用容器管理的事务。
最佳答案
这是正确的方法吗?
不,对于CMT,您的方法是您的交易单位。因此,在这里,所有的TransferRecord
都在同一唯一的事务中处理。
顺便说一句,您如何回滚交易?您传播RuntimeException
还是调用setRollbackOnly()
?我只是好奇。
还是应该在EJB外部运行for循环(对于每个TransferRecord)?
为什么在外面?没有什么可以强迫您这样做。如果要在自己的事务中处理每个TransferRecord
,则应将它们传递给另一个 EJB方法(以下代码受this answer启发):// supposing processRecords is defined on MyStatelessRemote1 and process defined on MyStatelessLocal1
@Stateless
@TransationAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class MyStatelessBean1 implements MyStatelessLocal1, MyStatelessRemote1 {
@EJB
private MyStatelessLocal1 myBean;
public void processRecords(List<TransferRecord> objs) {
// No transactional stuff so no need for a transaction here
for(Object obj : objs) {
this.myBean.process(obj);
}
}
@TransationAttribute(TransactionAttributeType.REQUIRES_NEW)
public void process(TransferRecord transferRecord) {
// Transactional stuff performed in its own transaction
// ...
}
}
如何确保会话未关闭但事务已回滚(仅针对特定失败的事务)
我想我涵盖了那部分。