Es gibt viele Möglichkeiten, eine so genannte ternäre Beziehung mit Hibernate zu implementieren, indem entweder "simple" map oder die Verknüpfung mithilfe einer zwischengeschalteten Entität/Tabelle implementiert wird. Ihre Anwendungsfälle entscheiden, welcher der richtige ist. Es hängt davon ab, wie die Daten gespeichert sind und wie oft Sie sie lesen. Auch das Reporting ist ein wichtiger Anwendungsfall.
Wenn Sie viele Benutzer - Projekt - Rollenkombinationen zulassen möchten, ist eine Zuordnung (z. B. auf der Benutzerentität) nicht wirklich geeignet, da Ihr Schlüssel entweder das Projekt oder die Rolle wäre und ein Schlüssel nur einmal angezeigt werden könnte. Trotzdem sollte jeder Beziehungseintrag in Ihrem System eindeutig sein, so dass ich in diesem Fall die Zwischentabelle mit mindestens einer eindeutigen Einschränkung betrachten würde.
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
}
Weiteres (desto besser) Ansatz wäre Ihre Beziehung Objektkennung als Verbundschlüssel zu verwenden:
Die „quick and dirty“ Art und Weise würde ein Unternehmen wie sein. Dies ist etwas ausführlicher, aber Sie benötigen keinen zusätzlichen Ersatzschlüssel, damit Ihre Join-Tabelle sauberer ist.
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;
}
}
}
Das Mapping auch wirklich einfach ist, sind die einzigen außergewöhnliche Teile der @JoinColumn(name = "...Id", insertable = false, updatable = false)
Ergänzungen. Damit können Sie Ihre zugeordnete Entität (für Navigationszwecke) verwenden, ohne sie zweimal zu speichern.
Welche Beziehung hat UserProjectRole zu anderen Entitäten? ODER Verwendung der UserProjectRole-Tabelle? –
Ich verwende es, um zu speichern, welcher Benutzer welche Rolle in welchem Projekt hat. Zum Beispiel hat Benutzer "A" die Rolle "ScrumMaster" im Projekt "P". –
Kann ein Benutzer mehrere Rollen in einem Projekt haben? z.B. Benutzer A ist sowohl Scrummaster als auch Entwickler in Projekt P? – dcsohl