もちろん答えはイエスです。しかし、昨日何が起こっていたのでしょうか?
問題は永続コンテキストにあり、メソッド名にもある可能性があります。フィールドはそのセッターで更新されませんでした。永続コンテキストはトランザクションにバインドされています。したがって、複数のフィールドを更新して保存する必要がある場合は、1つのトランザクション内ですべての操作を実行する必要があります。トランザクションを開始し、エンティティでセッターを呼び出し、エンティティへのアクセスを管理するセッションBeanでupdateメソッドを呼び出す必要があります。
@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
}
ゲッターは、トランザクション内で呼び出される場合と呼び出されない場合があります。ただし、セッターは既存のトランザクション内で呼び出す必要があります。同じトランザクション属性がセッション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);
}
}
すべてを1つのトランザクション内で実行する必要があります。
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();