Juni 21st, 2006

ManyToOne oder ManyToMany mit zusätzlichen Attributen

Posted by frank in Java, J2EE, Hibernate

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.

3 Responses to ' ManyToOne oder ManyToMany mit zusätzlichen Attributen '

Subscribe to comments with RSS or TrackBack to ' ManyToOne oder ManyToMany mit zusätzlichen Attributen '.

  1. and said,

    on April 21st, 2008 at 11:31 am

    Hallo,
    Ich weiß der Beitrag ist schon etwas älter, aber ich habe in einem Projekt genau das oben beschriebene Problem. Ich will eine ManyToMany-Beziehung auflösen und in die Beziehungstabelle zusätzliche Attribute bringen. Das genannte Beispiel funktioniert jedoch leider nicht. Ich bekomme immer eine RollbackException (Can’t commit because the transaction is in aborted state)

    Wo könnte der Fehler liegen? Gibt inzwischen vielleicht andere Möglichkeiten so eine Beziehung zu realisieren? Sämtliche Literatur schweigt sich über dieses Thema aus.

    Ich arbeite mit JBoss 4.2.2, also Hibernate auf einer MySQL 5 DB.

  2. frank said,

    on April 21st, 2008 at 2:23 pm

    Das Problem ist Heute so aktuell wie damals. Vom Standard her sind in einer einfachen ManyToMany-Beziehung keine zusätzlichen Attribute vorgesehen, sodass man hier immer über eine eigene Entität gehen muss.
    Der von Dir beschriebene Fehler scheint aber nur ein Folgefehler zu sein (Commit wird versucht, aber Transaktion ist aufgrund einer Exception bereits auf Abort gestellt). Von daher muss es schon vorher einen Grund für den Fehler geben.


  3. on Januar 5th, 2009 at 5:29 pm

    […] Beziehungsdefinition bzw. Cascadingangaben sind auch bei ManyToMany-Beziehungen mit zusätzlichen Attributen zu empfehlen. Die Angabe von den Hibernatespezifischen Cascading-Types steuert bei der Verwendung […]

Leave a reply

:mrgreen: :neutral: :twisted: :shock: :smile: :???: :cool: :evil: :grin: :oops: :razz: :roll: :wink: :cry: :eek: :lol: :mad: :sad: