如何避免无状态会话Bean中的并发?

时间:2012-07-03 12:51:50

标签: java ejb ejb-3.0 stateless-session-bean

我有一个SLSB,可以增加实体中的数字。如果两个线程同时到达SLSB,我在两个请求中都会得到相同的数字。

SLSB摘录

@Stateless(mappedName = "ejb/CustomerManager")
public class CustomerManagerBean implements CustomerManager {
...
    public String recoverName(int id) {
        Customer customer = (Customer) em.createQuery("from Customer where id = :id").setParameter("id", id).getSingleResult();     
        int oldValue = customer.getValue();
        int newValue = oldValue + 1;
        customer.setValue(newValue);        
     [BP]   return customer.getName() + " value=" + customer.getValue();
    }
...
}

实体提取

@Entity
public class Customer implements Serializable {
    @Id
    private int id;
    private int value;
}

为了测试问题,我在SLSB recoverName方法中标有[BP]的行上有一个断点。然后从两个分开的浏览器页面进行两次调用。在断点处,两个调用的值是相同

当第二次调用尝试使用setter修改值时,是否应该抛出某种异常?

我使用JBoss 5作为AS,使用MySql或Oracle作为数据库(同时尝试使用)

感谢您的帮助

1 个答案:

答案 0 :(得分:4)

如果您向实体添加了一个@Version注释字段,那么在刷新时会出现异常,JPA将使用该字段进行乐观锁定。

每次JPA更新实体时,它都会将内存中的版本与数据库中的版本进行比较,如果它们不匹配则会抛出异常。如果匹配,则版本将递增。

只需将以下内容添加到您的实体:

@Column(name = "version")
@Version
private long version;

(当然,将相应的列添加到数据库中)