2016-08-13 25 views
1

私は3つのテーブルを持っています。私はそれらに加わりたいと思います。3つのテーブルを結合するHibernateとJPA

Tabels:タスク プロジェクト ユーザー

が、それらはすべて、それらの間の多対多関係を持っている:プロジェクトは、複数のユーザーおよびその逆を持っており、またタスクが複数のユーザーを持っているように逆もまた同様であり、プロジェクトおよびユーザにとっても同様である。 ** 1 **このように3つのエンティティへの参加:

プロジェクト

私はJPA &休止状態でそれを実装する方法を見つけるためにしようとしていると私は2つの選択肢があり

@ManyToMany(fetch = FetchType.EAGER, 
    cascade = 
    { 
      CascadeType.DETACH, 
      CascadeType.MERGE, 
      CascadeType.REFRESH, 
      CascadeType.PERSIST 
    }, 
    targetEntity = User.class) 
    @JoinTable(name = "Collaborators", 
      joinColumns = @JoinColumn(name = "ProjectFk", referencedColumnName = "id", updatable=false, nullable=false), 
      inverseJoinColumns = @JoinColumn(name = "UserFk", referencedColumnName = "id", updatable=false, nullable=false)) 
    private Set<User> users = new HashSet<>(); 

ユーザー

@ManyToMany(fetch = FetchType.EAGER, 
      cascade = 
       { 
         CascadeType.DETACH, 
         CascadeType.MERGE, 
         CascadeType.REFRESH, 
         CascadeType.PERSIST 
       }, 
       targetEntity = Project.class) 
    @JoinTable(name = "Collaborators", 
      joinColumns = @JoinColumn(name = "UserFk", referencedColumnName = "id", updatable=false, nullable=false), 
      inverseJoinColumns = @JoinColumn(name = "ProjectFk", referencedColumnName = "id", updatable=false, nullable=false)) 
    private Set<Project> projects = new HashSet<>(); 

タスク

@ManyToMany(fetch = FetchType.EAGER, 
     cascade = 
     { 
       CascadeType.DETACH, 
       CascadeType.MERGE, 
       CascadeType.REFRESH, 
       CascadeType.PERSIST 
     }, 
     targetEntity = User.class) 
    @JoinTable(name = "Collaborators", 
     joinColumns = @JoinColumn(name = "TaskFk", referencedColumnName = "id", updatable=false, nullable=false), 
     inverseJoinColumns = @JoinColumn(name = "ProjectFk", referencedColumnName = "id", updatable=false, nullable=false)) 
    @MapKeyJoinColumn(name = "User_id") 
    @ElementCollection 
    private Map<Project, User> projectUserMap = new HashMap<>(); 

しかし、ここで、

を動作するようには思えdosn't:第四エンティティを作成し、コラボレーターそれに名前を付けた後、探してみてくださいこのSQLクエリを実装する方法:

select * from (
select user.id, Project.id, Task.id 
inner join Project on user.join_key = Project.join_key 
inner join Task on task.join_key = = Project.join_key 
) collaborator 

助けがあればMUCHがお勧めです。ありがとう。

+0

私はちょうどあなたの設定を見て、多くのエラーと冗長性を見つけます。それについて深く理解するために、JPA Collection Mappingについてさらに研究してください。 –

+0

これは、私がこれらの3つのテーブルをどのように結合するかについてはわかりませんからです。私はプロジェクトとユーザで最初は簡単に成功しましたが、3者関係では少し難しいです。 –

+1

*私はmappedByを使用しません。なぜなら、削除操作のやり方を制御したいからです。*:これはあなたがやっている大きな誤りです。 mappedByと削除のcoltrollingは、eash otherとは関係ありません。双方向の関連付けでは、一方の側は逆の側でなければなりません**したがって、mappedByを使用してください。あなたは仕事で喧嘩をしてもあまり意味がありません。 3つのManyToMany関連がある場合、3つの異なる結合テーブルが必要です。 –

答えて

1

は、以下のように実施されるべきである:

Projectクラス

@Entity 
public class Project extends ABaseEntity{ 

private Set<User> users = new HashSet<>(); 

@ManyToMany 
@JoinTable(name = "Collaborators", 
     joinColumns = @JoinColumn(name = "Project_ID", referencedColumnName = "id", updatable=false, nullable=false), 
     inverseJoinColumns = @JoinColumn(name = "User_ID", referencedColumnName = "id", updatable=false, nullable=false)) 
public Set<User> getUsers() { 
    return users; 
} 

public void setUsers(Set<User> users) { 
    this.users = users; 
} 
} 

Userクラス

@Entity 
@Table(name = "EMA_USER") 
public class User extends ABaseEntity { 

private Set<Project> projects = new HashSet<>(); 


@ManyToMany(fetch = FetchType.EAGER, 
     cascade = CascadeType.ALL, 
     targetEntity = Project.class) 
@JoinTable(name = "Collaborators", 
     joinColumns = @JoinColumn(name = "User_ID", referencedColumnName = "id", updatable = false, nullable = false), 
     inverseJoinColumns = @JoinColumn(name = "Project_ID", referencedColumnName = "id", updatable = false, nullable = false)) 
public Set<Project> getProjects() { 
    return projects; 
} 

public void setProjects(Set<Project> projects) { 
    this.projects = projects; 
} 
} 

Taskクラス

あなたのタスククラスで間違っている何
@Entity 
public class Task extends ABaseEntity{ 

private Map<Project, User> projectUserMap = new HashMap<>(); 

@ManyToMany(
     fetch = FetchType.EAGER, 
     cascade = CascadeType.ALL 
) 
@JoinTable(
     name = "Collaborators", 
     joinColumns = @JoinColumn(name = "Task_ID", referencedColumnName = "id", updatable = false, nullable = false), 
     inverseJoinColumns = @JoinColumn(name = "User_ID", referencedColumnName = "id", updatable = false, nullable = false) 
) 
@MapKeyJoinColumn(name = "Project_Id") 
public Map<Project, User> getProjectUserMap() { 
    return projectUserMap; 
} 

public void setProjectUserMap(Map<Project, User> projectUserMap) { 
    this.projectUserMap = projectUserMap; 
} 
} 

:@MapKeyJoinColumnがキーの列をマップするために使用される

@MapKeyJoinColumn(name = "User_id") 

は、ここではプロジェクトエンティティです。

@ElementCollection 

が使用されるマップの値が@Embeddableある場合

@JoinTable 

(ここで、タスクとユーザとの間の関係である)マップの値で定義されたエンティティとエンティティクラスとの関係を規定します。

targetEntity = User.class 

定義済みジェネリックタイプのコレクションを使用したため、すべてのtargetEntityは冗長です。

また、このような3つのクラスを設定する必要はありません。私が理解する限り、これらの3つのクラス間の関係を含むテーブルが必要です。あなたがユーザーを与えているすべてのコラボレーションを見つけることができ、分離コラボレーションエンティティと

@Entity 
public class Collaboration{ 
    @ManyToOne 
    private User user; 
    @ManyToOne 
    private Task task; 
    @ManyToOne 
    private Project project; 
} 

: は、だから、このようにコラボレーションと呼ばれるエンティティを定義します。

このエンティティがないと、指定したユーザーに関連するすべてのタスクを検索し、もちろんプロジェクトとタスクをJavaコードで収集するクエリを作成できます。 クエリは次のようになります

'Select t from Task t join projectUserMap m where m = :user ' 
+0

お返事ありがとうございます。誰があなたを落胆させたのか分かりませんが、私ではありません!あなたがここで説明するのを気にするならば、3つのテーブルはリンクされていますか?私のポイントは、**テーブル**のコラボレーションを呼び出して**タスク**と**与えられたユーザー**のプロジェクト**を取得する場合です。**私はそれらを取得しますか? –

+0

私はあなたに理解を助けることができるかどうか気にします。ノンエクスペリエンスユーザーからのダウンワードは私にとっては問題ではありません。何か問題が生じた場合は、ここにお尋ねください。私はあなたの質問に関する私の答えを更新しました。 –

+0

私の答えがあなたの要求を満たしているなら、他の人が将来同じ質問をするかもしれないので、正しいものとしてマークしてください。 –

関連する問題