EXTENDED_PERSISTENT_CONTEXT を使用して、複数の呼び出しにわたって状態を維持しようとしています。私の理解では、管理されたエンティティは呼び出し間で切り離されませんが、以前に検証エラーをスローした後、呼び出しで切り離されたエンティティに関連するエラーが発生し続けます。状態はステートフル セッション Bean で維持されています。
@Named(SessionFacadeBean.SEAM_NAME)
@SessionScoped
@Stateful
@LocalBean
@AccessTimeout(value = 10, unit = TimeUnit.SECONDS)
public class SessionFacadeBean implements Serializable
{
public static final String SEAM_NAME = "sessionCacheBean";
@PersistenceContext(unitName = GlobalParameters.BACKEND_CODE_PERSISTENCE_CONTEXT_NAME, type = PersistenceContextType.EXTENDED)
private EntityManager em;
private ParentOne sessionData;
public synchronized ParentOne getSessionData() {
if(sessionData == null) {
sessionData = new ChildTwo();
}
return sessionData;
}
public boolean getLock() {
return true;
}
public void clearLock() {
}
// Other stuff I don’t ‘think’ is relevant.
}
(簡略化された)状態は、休止状態を使用して保存されています。これは 3 つのクラス (親と 2 つの子で、そのうちの 1 つには子のリストが含まれます) で構成されます。
@XmlRootElement(name = XMLConstants.COMPONENT_ELEMENT_NAME_IN_XML)
@XmlAccessorType(XmlAccessType.NONE)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "Class", length = 50)
@Entity
public class ParentOne
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@XmlElement(name = "ID")
private Long iD;
@XmlElement(name = "name")
protected String friendlyName = "";
}
@XmlRootElement(name = XMLConstants.COMPONENT_ELEMENT_NAME_IN_XML)
@XmlAccessorType(XmlAccessType.NONE)
@Entity
public class ChildOne extends ParentOne
{
public ChildOne(String name, ParentOne child) {
super(name);
myChild = child;
}
@ManyToOne(cascade = CascadeType.ALL)
protected ParentOne myChild;
}
@XmlRootElement(name = XMLConstants.COMPONENT_ELEMENT_NAME_IN_XML)
@XmlAccessorType(XmlAccessType.NONE)
@Entity
public class ChildTwo extends ParentOne
{
public ChildTwo() {
super(“common”);
}
}
次のように、ステートレス Bean からステートフル Bean にアクセスしています。
@Stateless
@LocalBean
@Path("/")
public class MyService
{
@PersistenceContext(unitName = GlobalParameters.BACKEND_CODE_PERSISTENCE_CONTEXT_NAME)
private EntityManager em;
@Inject
private SessionFacadeBean sessionBean;
@POST
@Path("/create/item")
@ValidateRequest
public ComponentShortSummary addItem(@Form NewItemForm itemForm)
{
if(sessionBean.getLock()) {
try {
if(itemForm.getName().equals("INVALID") == true) {
throw new ConstraintViolationException("Failed", new HashSet<ConstraintViolation<?>>());
}
ChildOne child = new ChildOne(itemForm.getName(), sessionBean.getSessionData());
em.persist(child);
return null;
}
finally {
sessionBean.clearLock();
}
} else {
return null;
}
}
}
問題を再現するために、次のシーケンスを実行します。
- 有効な名前で addItem を呼び出します (これにより、項目がデータベースに永続化されます)。
- 「INVALID」という名前で addItem を呼び出すと、制約例外がスローされます。
- 有効な名前を指定して addItem を呼び出します (これにより、ライン
em.persist(child)
.
私が理解していないのは、分離されたエンティティで終わる方法/理由です。実際のコードでは、状態を変更する前に、要求/状態の検証を実行します (そのため、状態が分離されていることがわかる理由はありません)。
への呼び出しを削除するとsessionBean.getLock()
、問題は解決します (オブジェクトは正しく保持されます)。ロック メソッドの目的は基本的にセッション状態へのアクセスをシリアル化することですが、現在getLock()
メソッドは空です。問題は、例外をスローする前にステートフル Bean を呼び出しているという事実に関連しているように感じます。
私のエンティティが分離される結果となる何が起こっているのか、誰かが説明できますか/それを回避する方法がある場合(理想的には、説明をサポートするドキュメントを教えてください)?
ステートフル Bean にアクセスする前に検証を実行して、現在の問題を回避する方法はおそらくあると思いますが、一般的なケース (ステートフル Bean が呼び出しでアクセスされた後に例外がスローされる場合) について心配しています。拡張された永続コンテキストからエンティティを切り離したくない場合に、例外を処理するための受け入れられた戦略はありますか?