答案当然是肯定的。但是昨天发生了什么?
问题出在持久性上下文中,也可能出在方法名称中。该字段未在其设置器中更新。持久性上下文与事务绑定。因此,如果您需要更新和保存多个字段,则必须在一个事务中完成所有操作。您必须启动事务、调用实体上的设置器并调用会话 bean 上的更新方法来管理对实体的访问。
@Basic(fetch=FetchType.LAZY)
String field;
@Override
@TransactionAttribute(TransactionAttributeType.SUPPORTS)
public String getFiled() {
return field;
}
@Override
@TransactionAttribute(TransactionAttributeType.MANDATORY)
public void setText(String text) {
//other code
this.field = text;
//other code
}
在事务中可以调用或不调用 getter。但是必须在现有事务中调用 setter。相同的事务属性适用于会话 bean 的更新方法。此外,我们需要一种方法reattach()
来确保我们在适当的持久性上下文中使用对象。
@Stateless
class AccessBean implements Accessor {
@PersistenceContext(unitName = "MyUnit")
private EntityManager manager;
@TransactionAttribute(TransactionAttributeType.MANDATORY)
public TheEntity update(TheEntity e) {
e = manager.merge(e);
manager.flush();
return e;
}
@TransactionAttribute(TransactionAttributeType.MANDATORY)
public <T> T reattach(T object) {
return manager.merge(object);
}
}
所有这些都必须在一笔交易中完成。
Context context = new InitialContext(your properties);
UserTransaction trans = (UserTransaction)context.lookup("java:comp/UserTransaction");
//AccessBean ab already injected;
//TheEntity e already exists
trans.begin(); //this implicates a new persistent context
e = da.reattach(e); //critical line
e.setText("New text");
e = da.updateEvent(e);
trans.commit();
TestCase.assertEquals("New text", e.getField()); //yes!
关键线是看似不必要的线,但事实并非如此。如果您将此行注释掉,您将使用分离或附加到另一个持久上下文的实体。然后你会看到有趣的行为,这是我的问题。
注意:到目前为止,我们还需要在显式事务中获取数据。
trans.begin();
e = da.reattach(e);
String s = e.getField();
trans.commit();