Java EE 6 - 悲观锁定 - ViewScoped bean +有状态bean,具有UserTransaction,PreDestroy和其他问题 [英] Java EE 6 - Pessimistic Locking - ViewScoped bean + Stateful bean with UserTransaction, PreDestroy and other problems

查看:198
本文介绍了Java EE 6 - 悲观锁定 - ViewScoped bean +有状态bean,具有UserTransaction,PreDestroy和其他问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我正在处理的应用程序中,我们需要在用户输入编辑页面(锁定当前编辑的DB记录)之前启动事务,并在单击按钮或离开页面时结束它。

In application I'm working on we need to start transaction before user enters 'edit page' (to lock DB records currently edited) and end it when he clicks the button or left the page.

为此,我使用 @Stateful 管理事务的EJB bean和CDI @ViewScoped '编辑页面'上使用的bean。

For this purpose I use @Stateful EJB bean which manages the transaction and CDI @ViewScoped bean which is used on the 'edit page'.

当然,用户可以在编辑页面上执行许多操作,这些操作应该在同一个事务中调用。
以下是示例代码:

Of course user can take many actions on edit page, which are supposed to be invoked within the same transaction. Here's sample code:

@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";
  }
}

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

In theory it looks fine, but we have some questions:


  1. 我们能否确保在同一笔交易中调用所有操作?

  2. 如果用户关闭选项卡/浏览器/通过键入地址栏或http会话超时转到另一个URL。我们如何检测它并回滚事务?起初我们尝试使用 @PreDestroy ,但看起来它从未被调用过!

  1. Can we be sure that all operations are invoked in the same transaction?
  2. What if user closes tab/browser/goes to another URL by typing in address bar or http session times out. How can we detect it and rollback the transaction? At first we tried with @PreDestroy but it looks like it's never called!

我们使用Java EE 6技术:JSF,EJB。部署在Glassfish 3.1.2 Web Profile上。我们使用MyBatis而不是JPA。
感谢您的帮助

We use Java EE 6 technologies: JSF, EJB. Deploy on Glassfish 3.1.2 Web Profile. We use MyBatis instead JPA. Thanks for help

推荐答案

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

IMHO it's very bad approach. you lock your table and wait hoping that user does something. it may take minutes. all other users will have to wait for this one - in most applications it's unacceptable. you shouldn't span transaction between between multiple http requests.

但是,如果你坚持,回滚必须不依赖于某些外部事件。只需设置一个事务超时

however, if you insist, rollback must not depends on some external events. simply set a transaction timeout

这篇关于Java EE 6 - 悲观锁定 - ViewScoped bean +有状态bean,具有UserTransaction,PreDestroy和其他问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆