2

セッションスコープにJSFマネージドBeanがあり、これには、認証されたユーザーなど、トレースするエンティティが含まれています。

@ManagedBean
@SessionScoped
public class LoginController implements Serializable {
  User user;

  public User getUser() {
    return this.user;
  }

  public void setUser(User user) {
    this.user = user;
  }
  /* ... */
}

別のBeanでは、次のように、それに関連するロールのリストを取得するためにそれを使用するようにユーザーに注入する必要があります。

@ManagedBean
@ViewScoped
public class AnotherController implements Serializable {

  List<Role> roles;      

  @ManagedProperty(value="#{loginController.user}")
  User user;

  public someMethod() {
    /* Some stuff that insert other roles into database, referring the user as owner */
    roles = user.getRolesList();
  }
}

を使用してajaxでページを更新してもsomeMethodrolesリストはリロードされません。このエラーが発生するem.refresh(user)前に挿入すると、次のようになります。user.getRolesList

Can not refresh not managed object: model.User[ id=1 ].

誰かが私がこれを理解するのを手伝ってくれる?別のBeanに注入された場合、セッションスコープのエンティティが管理されないのはなぜですか?どうすればこれを修正できますか?ありがとうございました。

4

2 に答える 2

7

エンティティを更新できるようにするには、エンティティを管理する必要がありますが、それはすでにわかっています。管理するには、次のいずれかである必要があります

  • 再フェッチ
  • マージしてから更新
  • 拡張された永続コンテキストで管理されたまま

最初の2つのオプションにはトランザクションが必要です。

@ManagedBeanいかなる種類のトランザクション管理も暗示していないため@ViewScoped、これらのBean内のエンティティは常に切り離されます。したがって、発生している動作は、予想されるJPAの動作です。

最初の2つのオプションでは、リクエストをバックエンドのトランザクション対応EJBに渡すことができます。これにより、エンティティがマージされて更新されるか、新しくフェッチされたエンティティが返されます。Java EEアプリケーションサーバーを使用していない場合は、を使用できますUserTransaction

3番目のオプションでは、拡張永続コンテキストを使用できます。これは、各トランザクションの後で閉じられないため、エンティティはトランザクションの境界を越えて管理されたままになります。

編集UserTransaction依存性注入を使用および想定して、これを修正するための最も簡単なオプション。

@Inject
UserTransaction tx;

    //merging and refreshing
    tx.begin();
    User managedUser = em.merge(user);
    em.refresh(managedUser);
    tx.commit();
    user = managedUser;

    //refetching
    tx.begin();
    user = em.find(User.class, user.getId);
    tx.commit();
于 2013-02-25T10:05:10.747 に答える
1

まず、懸念事項を分離する必要があります。これは、基本的に、バッキングBeanがビジネスロジックを直接実行してはならないことを意味します(コメントによって暗示されます/* Some stuff that insert other roles into database, referring the user as owner */)。代わりに、アノテーションを付けUserServiceてマネージドBeanにクラスを挿入し@EJB、commandComponentsのアクションを介してそのメソッドを呼び出すことができます。

次に、データベースからエンティティを取得し、それを永続コンテキストから切り離すと(読み取り:永続コンテキストはトランザクションの終了時に閉じられます)、エンティティは永続サービスによって管理されなくなり、エンティティへの変更は行われません。データベースに反映されます。そうしたい場合はEntityManager.merge()、エンティティを永続化するために、を呼び出す必要があります。LoginController.userオブジェクト内のカンジをデータベースに永続化する場合は、これを行う必要があります。

したがって、Kostjaが言うことは、ユーザーオブジェクトとデータベース内の行の間の最新の対応を取得する場合、EntityManager彼が提案した方法の1つに従って、オブジェクトを管理する必要があるということです。

于 2013-02-25T11:25:21.057 に答える