で三元関係を実装する、私は4 tables.entitiesを持って休止状態
- ユーザー
- プロジェクト
- UserProjectRole
私のシナリオや関係1つのプロジェクトでは、ある
ありがとうございます。
で三元関係を実装する、私は4 tables.entitiesを持って休止状態
私のシナリオや関係1つのプロジェクトでは、ある
ありがとうございます。
Hibernateと呼ばれる、いわゆる"simple" mapを利用するか、中間のエンティティ/テーブルを使用して関連付けを実装する、という3つの関係を実装する方法はたくさんあります。あなたのユースケースはどちらが正しいかを決定します。それは、データがどのように格納され、どのように(しばしば)それを読むかによって異なります。また、レポートは重要な使用例です。
多くのユーザプロジェクトロールの組み合わせを許可したい場合、あなたのキーはおそらくプロジェクトまたはロールのいずれかになり、キーは一度しか表示されないため、マップ(たとえば、ユーザーエンティティ上)は実際には適切ではありません。それにもかかわらず、すべてのリレーションエントリはシステム内で一意でなければならないので、この場合、私は少なくともいくつかのユニーク制約を持つ中間テーブルになりがちです。
「間に合わせ」の方法は、のような実体のようになります。
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
@Entity
@Table(uniqueConstraints = @UniqueConstraint(columnNames={"user_id", "project_id", "role_id"}))
public class UserProjectRoleSimple {
@Id
@GeneratedValue
private Long id;
@ManyToOne
private User user;
@ManyToOne
private Project project;
@ManyToOne
private Role role;
// you also need constructors, getters, equals, hashcode and stuff
}
別の(より良い)のアプローチは、複合キーとしてあなたの関係のオブジェクト識別子を使用することです。これはもう少し冗長ですが、追加のサロゲート・キーを必要としないので、結合表はより洗練されたものになります。マッピングも本当に簡単であることを
import java.io.Serializable;
import javax.persistence.Embeddable;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.validation.constraints.NotNull;
import org.hibernate.annotations.Immutable;
@Entity
@Immutable
public class UserProjectRole {
protected UserProjectRole() {
}
public UserProjectRole(final User user, final Project project, final Role role) {
this.userProjectRoleId = new UserProjectRoleId(user, project, role);
this.user = user;
this.project = project;
this.role = role;
}
@EmbeddedId
protected UserProjectRoleId userProjectRoleId;
@ManyToOne
@JoinColumn(name = "userId", insertable = false, updatable = false)
private User user;
@ManyToOne
@JoinColumn(name = "projectId", insertable = false, updatable = false)
private Project project;
@ManyToOne
@JoinColumn(name = "roleId", insertable = false, updatable = false)
private Role role;
public User getUser() {
return user;
}
public Project getProject() {
return project;
}
public Role getRole() {
return role;
}
@Embeddable
static class UserProjectRoleId implements Serializable {
private static final long serialVersionUID = 7994974851694559677L;
@NotNull
private Long userId;
@NotNull
private Long projectId;
@NotNull
private Long roleId;
protected UserProjectRoleId() {
}
protected UserProjectRoleId(final User user, final Project project, final Role role) {
this.userId = user.getId();
this.projectId = project.getId();
this.roleId = role.getId();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((projectId == null) ? 0 : projectId.hashCode());
result = prime * result + ((roleId == null) ? 0 : roleId.hashCode());
result = prime * result + ((userId == null) ? 0 : userId.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
UserProjectRoleId other = (UserProjectRoleId) obj;
if (projectId == null) {
if (other.projectId != null)
return false;
} else if (!projectId.equals(other.projectId))
return false;
if (roleId == null) {
if (other.roleId != null)
return false;
} else if (!roleId.equals(other.roleId))
return false;
if (userId == null) {
if (other.userId != null)
return false;
} else if (!userId.equals(other.userId))
return false;
return true;
}
}
}
、唯一の特別な部品が@JoinColumn(name = "...Id", insertable = false, updatable = false)
追加されています。これで、マッピングされたエンティティをナビゲーション目的で2回保存せずに使用できます。
UserProjectRoleと他のエンティティとの関係はどのようなものですか。またはUserProjectRoleテーブルの使用? –
私はそれを使って、どのユーザがどのプロジェクトにどのような役割を持っているかを保存します。たとえば、ユーザー "A"は、プロジェクト "P"で役割 "ScrumMaster"を持っています。 –
ユーザはプロジェクト内で複数のロールを持つことができますか?例えばユーザーAはプロジェクトPのscrummasterと開発者の両方ですか? – dcsohl