2

子エンティティのリストを持つJPAエンティティがあります。この場合、ロールがアタッチされたユーザーエンティティです。

次のようになります(少し簡略化されています-一部のフィールド/メソッドは省略されています)。

@Entity
public class MyUser{

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private Long myUserId;

 private String username; 

 @OneToMany
 @JoinTable(name = "userrole",
   joinColumns = {
     @JoinColumn(name="myUserId", unique = true)           
   },
   inverseJoinColumns = {
     @JoinColumn(name="roleId")
   }
 )
 private Collection<Role> roles;    

 public Collection<Role> getRoles() {
     return roles;
 }
}

ストレスを感じる場合、Roleエンティティは非常に単純です。

@Entity
public class Role {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long roleId;
  private String role; // a few more string fields here .

2人のユーザーとユーザーごとに数百のロールを追加すると、ユーザーを一覧表示するときに奇妙な動作が発生します。各ユーザーは数百回リストされます(同じユーザー=同じ一意のID)。

問題のあるコード:

Query q = em.createQuery("SELECT u FROM MyUser u LEFT JOIN FETCH u.roles");
Collection<MyUser> users = q.getResultList();

for(MyUser u : users){
     // print/use u here
} 

ただし、データベースにアクセスしてselectステートメントを実行するだけでは、問題ないようです。すべてのユーザーは一度だけ存在します。

この場合、OpenJPA1.2をIBMDB2データベースと一緒に使用します。

4

2 に答える 2

2

モデルが間違っていると思います。通常、ユーザーとロールの関係はOneToManyではなく「ManyToMany」であるため、コードを次のように変更する必要があります。

@Entity
public class MyUser{

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private Long myUserId;

 private String username; 

 @ManyToMany //This should be many to many
 @JoinTable(name = "userrole",
   joinColumns = {
     @JoinColumn(name="myUserId") //The userId in the join table should
                                  //NOT be unique because the userId can
                                  //be many times with different roles
   },
   inverseJoinColumns = {
     @JoinColumn(name="roleId")
   }
 )
 private Collection<Role> roles;    

 public Collection<Role> getRoles() {
     return roles;
 }
}

この方法を試して、機能するかどうかを確認してください。

また、クエリは左結合を必要としないはずです。各エンティティでgetRoles()メソッドを使用すると(LAZY Fetchを使用)、JPAによってロールが自動的にフェッチされる必要があります。

于 2012-08-09T15:14:34.007 に答える
1

実際には、UserエンティティとUserRoleエンティティに@ManyToManyマッピングを設定するのが妥当です。クエリの問題は、結合テーブルから必要のないすべての行が返されることです。group by uしたがって、次のようにクエリに追加するだけです。

SELECT u FROM MyUser u LEFT JOIN FETCH u.roles GROUP BY u

そして、あなたは終わります。

于 2012-08-11T04:30:07.183 に答える