Java EE 6 - 悲观锁定 - 带有UserTransaction,PreDestroy和其他问题的ViewScoped bean +有状态bean

时间:2012-09-29 18:32:43

标签: java-ee transactions java-ee-6 stateful-session-bean pessimistic-locking

在我正在处理的应用程序中,我们需要在用户输入“编辑页面”(锁定当前编辑的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";
  }
}

理论上它看起来不错,但我们有一些问题:

  1. 我们能确定在同一个交易中调用所有操作吗?
  2. 如果用户通过键入地址栏或http会话超时来关闭标签/浏览器/转到另一个URL,该怎么办?我们如何检测它并回滚事务?起初我们尝试使用@PreDestroy,但看起来它从未被调用过!
  3. 我们使用Java EE 6技术:JSF,EJB。部署在Glassfish 3.1.2 Web Profile上。我们使用MyBatis而不是JPA。 谢谢你的帮助

1 个答案:

答案 0 :(得分:0)

恕我直言,这是非常糟糕的做法。你锁定你的表并等待希望用户做某事。可能需要几分钟。所有其他用户将不得不等待这一个 - 在大多数应用程序中它是不可接受的。你不应该在多个http请求之间跨越事务。

但是,如果你坚持,回滚一定不能取决于一些外部事件。只需设置一个事务超时