Hin und wieder hat man bei @ManyToOne und @ManyToMany Beziehungen zwischen Entitäten auch noch Attribute zu hinterlegen. Ein weiterer Anwendungsfall, dann halt ohne Attribute, ist die Auslagerung der ManyToOne-Beziehung in eine eigene Tabelle. Hibernate, welches mit dem JBoss 4.0.4.GA ausgeliefert wird, unterstützt leider derzeit noch keine @JoinTable in Verbindung mit @OneToOne oder @ManyToOne. Das Mapping wird beim Deployment mit folgendem Fehler quittiert:
org.hibernate.cfg.NotYetImplementedException: association table on a single ended association is not yet supported
Es bleibt einem daher nichts anderes übrig, als die Beziehung als eigene Entität zu implementieren. In unserem Beispiel haben wir hier eine Klasse A und eine Klasse B, welche zusammen die Beziehung ManyToOne haben und diese in der Tabelle A2B gespeichert wird. Die Klassen sehen dann so aus:
@Entity
public class A {
@Id
private int id;
@OneToOne(fetch = FetchType.LAZY, mappedBy = “a”)
private A2B a2b;
}
@Entity
public class B {
@Id
private int id;
@OneToOne(fetch = FetchType.LAZY, mappedBy = “b”)
private A2B a2b;
}
@Entity
public class A2B {
@EmbeddedId
@AttributeOverrides( {
@AttributeOverride(name = “aId”, column = @Column(nullable = false)),
@AttributeOverride(name = “bId”, column = @Column(nullable = false))
})
private A2BId id;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = “aId”, insertable = false, updatable = false)
private A a;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = “bId”, insertable = false, updatable = false)
private B b;
}
@Embeddable
public class A2BId implements Serializable {
private int aId;
private int bId;
@Override
public boolean equals(Object other) {
if ((this == other))
return true;
if ((other == null))
return false;
if (!(other instanceof A2BId))
return false;
A2BId castOther = (A2BId) other;
return (aId == castOther.aId) && (bId == castOther.bId);
}
@Override
public int hashCode() {
int result = 17;
result = 37 * result + aId;
result = 37 * result + bId;
return result;
}
}
Wichtig hierbei ist der eigene PrimaryKey in Form eines @Embeddable - Objektes sowie das doppelte Mapping der Primary-Key-Spalten in der Beziehungstabelle. Wichtig ist hier, dass insertable und updateable beim zweiten Mapping auf false sind:
@JoinColumn(name = “aId”, insertable = false, updatable = false)
An die Klasse A2B könnten nun noch die angesprochenen weiteren Attribute gehangen werden zu der Beziehung. Um aus der ManyToOne eine ManyToMany-Beziehung auf Seiten von A und B zu machen, muss dort lediglich eine Collection der entsprechenden Beziehungsklasse angelegt werden und entsprechend statt mit @OneToOne mit @OneToMany gemappt werden.