5

したがって、Users テーブル、Projects テーブル、および User_Roles テーブルがあります。2 つのプロジェクトに接続されているユーザーが 1 人いますが、ロールが 1 つしかない場合は 2 つのプロジェクトが返されますが、ロールが 2 つある場合は 4 つのロール (2x2 プロジェクト) が返されます。これを防ぐにはどうすればよいですか

これは、ユーザーのプロジェクトのリストを返すための私のコードです

@Override
public List<Project> retrieve(User user) {
    Criteria criteria = super.createCriteria();
    criteria.addOrder(Order.desc("date"));
    criteria.createCriteria("users").add(Restrictions.eq("id", user.getId()));

    return (List<Project>) criteria.list();
}

User クラスのマッピング

@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "Users_Projects",
           joinColumns = @JoinColumn(name = "UserID"), inverseJoinColumns =   @JoinColumn(name = "ProjectID"))
public List<Project> getProjects() {
    return projects;
} 

@ElementCollection(fetch = FetchType.EAGER)
@Enumerated(EnumType.STRING)
@Column(name = "RoleType")
@JoinTable(name = "User_Roles", joinColumns = @JoinColumn(name = "UserID"))
public Set<Role> getRoles() {
    return roles;
}

ここで何が問題なのですか?

tnx

4

1 に答える 1

13

基準クエリからの重複行の問題に対する古典的な「修正」は、ページネーションと組み合わせようとしない限り機能する可能性が高く、追加することです

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

これは、ユーザー ロールの熱心な読み込みが原因で、あなたの状況で発生していると思います。それを怠惰に変更することも機能する可能性があり、ページネーションが必要な場合は引き続き機能します。

設定fetch = FetchType.EAGERは、ユーザーを取得するたびにユーザーのすべてのロールを常にロードするように hibernate に指示します。これは、常にロール テーブルに結合することによって実現されます。

残念ながら、その sql は同じユーザー (ロールごとに 1 つ) を持つ複数のレコードにつながり、sql の実行後に Java で整理する必要があります。これは、結果トランスフォーマーが行うことです。

さらに残念なことに、単純な hibernate 基準で最も自然な方法でページングを使用したい場合、 and を使用するcriteria.setFirstResultcriteria.setMaxResults、物事が間違った順序で発生するため、重複を避けるために結果トランスフォーマーを必要とするこれらのクエリは正しくページングされません。

すべての休止状態の sql 生成をもう少しよく理解するために、別の SO 休止状態の質問に対するこの回答で説明されているように、生成された sql のログ記録を有効にすることをお勧めします。

于 2012-07-03T22:14:11.073 に答える