在我正在处理的应用程序中,我们需要在用户输入“编辑页面”(锁定当前编辑的DB记录)之前启动事务,并在单击按钮或离开页面时结束它。
为此,我使用@Stateful
EJB bean来管理事务和在'编辑页面'上使用的CDI @ViewScoped
bean。
当然,用户可以在编辑页面上执行许多操作,这些操作应该在同一事务中调用。 这是示例代码:
@Stateful
@LocalBean
@TransactionManagement(TransactionManagementType.BEAN)
public class TransactionService {
@Resource
private UserTransaction utx;
@PostConstruct
private void postConstruct() {
System.out.println(this + " postConstruct");
}
@PreDestroy
private void preDestroy() {
System.out.println(this + " preDestroy");
utx.rollback();
}
public void start() {
utx.begin();
//lock db records with select ... for update
}
@Remove
public void commit() {
utx.commit();
}
@Remove
public void rollback() {
utx.rollback();
}
}
@Named
@ViewScoped
public class TestBean implements Serializable {
@Inject
private TransactionService ts;
@Inject
private SqlService sql; //stateless session bean
@PostConstruct
private void postConstruct() {
System.out.println(this + " postConstruct");
ts.start();
}
@PreDestroy
private void preDestroy() {
System.out.println(this + " preDestroy");
ts.rollback();
}
public void methodA() {
//do some db operation
sql.insert();
}
public void methodB() {
//do some db operation
sql.update();
}
public String save() {
ts.commit();
return "otherView";
}
public String cancel() {
ts.rollback();
return "otherView";
}
}
理论上它看起来不错,但我们有一些问题:
@PreDestroy
,但看起来它从未被调用过!我们使用Java EE 6技术:JSF,EJB。部署在Glassfish 3.1.2 Web Profile上。我们使用MyBatis而不是JPA。 谢谢你的帮助
答案 0 :(得分:0)
恕我直言,这是非常糟糕的做法。你锁定你的表并等待希望用户做某事。可能需要几分钟。所有其他用户将不得不等待这一个 - 在大多数应用程序中它是不可接受的。你不应该在多个http请求之间跨越事务。
但是,如果你坚持,回滚一定不能取决于一些外部事件。只需设置一个事务超时