JPA: Entity Klasse @JoinColumns Problem

Diskutiere JPA: Entity Klasse @JoinColumns Problem im Data Tier Forum; Hallo Leute, ich verwende Netbeans 7.4 auf meinen Mac und arbeite zur Zeit an einer Webanwendung. In Netbeans hab ich mir die Entity...

  1. Gongo82
    Gongo82 Neues Mitglied
    Hallo Leute,

    ich verwende Netbeans 7.4 auf meinen Mac und arbeite zur Zeit an einer Webanwendung.

    In Netbeans hab ich mir die Entity Klassen von meiner existierenden DB generieren lassen.

    Wenn ich die Anwendung laufen lasse wird die folgende Exception geworfen.

    The @JoinColumns on the annotated element [field tblSeminarCollection] from the entity class [class entities.TblDozent] is incomplete. When the source entity class uses a composite primary key, a @JoinColumn must be specified for each join column using the @JoinColumns. Both the name and the referencedColumnName elements must be specified in each such @JoinColumn.

    Ich suche schon seit Tagen nach einer Lösung und kann nichts finden das mir weiter helfen könnte, vielleicht weiss von euch jemand, was das Problem ist und kann mir einen Tip geben...wäre super!

    Hier die genaue Exception:

    Code (Java):

    Schwerwiegend:   Exception while invoking class org.glassfish.persistence.jpa.JPADeployer prepare method
    Schwerwiegend:   javax.persistence.PersistenceException: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.EntityManagerSetupException
    Exception Description: Predeployment of PersistenceUnit [jdbcNOK_PU] failed.
    Internal Exception: Exception [EclipseLink-7220] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.ValidationException
    Exception Description: The @JoinColumns on the annotated element [field tblSeminarCollection] from the entity class [class entities.TblDozent] is incomplete. When the source entity class uses a composite primary key, a @JoinColumn must be specified for each join column using the @JoinColumns. Both the name and the referencedColumnName elements must be specified in each such @JoinColumn.
        at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.createPredeployFailedPersistenceException(EntityManagerSetupImpl.java:1950)
        at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.predeploy(EntityManagerSetupImpl.java:1941)
        at org.eclipse.persistence.jpa.PersistenceProvider.createContainerEntityManagerFactory(PersistenceProvider.java:322)
        at org.glassfish.persistence.jpa.PersistenceUnitLoader.loadPU(PersistenceUnitLoader.java:199)
        at org.glassfish.persistence.jpa.PersistenceUnitLoader.<init>(PersistenceUnitLoader.java:107)
        at org.glassfish.persistence.jpa.JPADeployer$1.visitPUD(JPADeployer.java:223)
        at org.glassfish.persistence.jpa.JPADeployer$PersistenceUnitDescriptorIterator.iteratePUDs(JPADeployer.java:510)
        at org.glassfish.persistence.jpa.JPADeployer.createEMFs(JPADeployer.java:230)
        at org.glassfish.persistence.jpa.JPADeployer.prepare(JPADeployer.java:168)
        at com.sun.enterprise.v3.server.ApplicationLifecycle.prepareModule(ApplicationLifecycle.java:922)
        at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:431)
        at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:219)
        at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:491)
        at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:527)
        at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:523)

     
    Es geht um die nun folgenden Tabellen:

    Code (Java):


    package entities;

    import java.io.Serializable;
    import java.util.Collection;
    import javax.persistence.Column;
    import javax.persistence.EmbeddedId;
    import javax.persistence.Entity;
    import javax.persistence.JoinColumn;
    import javax.persistence.JoinTable;
    import javax.persistence.ManyToMany;
    import javax.persistence.ManyToOne;
    import javax.persistence.NamedQueries;
    import javax.persistence.NamedQuery;
    import javax.persistence.Table;
    import javax.validation.constraints.Size;
    import javax.xml.bind.annotation.XmlRootElement;
    import javax.xml.bind.annotation.XmlTransient;


    @Entity
    @Table(name = "tbl_Dozent")
    @XmlRootElement
    @NamedQueries({
        @NamedQuery(name = "TblDozent.findAll", query = "SELECT t FROM TblDozent t"),
        @NamedQuery(name = "TblDozent.findByDozId", query = "SELECT t FROM TblDozent t WHERE t.tblDozentPK.dozId = :dozId"),
        @NamedQuery(name = "TblDozent.findByDozName", query = "SELECT t FROM TblDozent t WHERE t.dozName = :dozName"),
        @NamedQuery(name = "TblDozent.findByDozNachname", query = "SELECT t FROM TblDozent t WHERE t.dozNachname = :dozNachname"),
        @NamedQuery(name = "TblDozent.findByDozTel", query = "SELECT t FROM TblDozent t WHERE t.dozTel = :dozTel"),
        @NamedQuery(name = "TblDozent.findByTblLoginUsersLoginEmail", query = "SELECT t FROM TblDozent t WHERE t.tblDozentPK.tblLoginUsersLoginEmail = :tblLoginUsersLoginEmail")})
    public class TblDozent implements Serializable {

        private static final long serialVersionUID = 1L;
        @EmbeddedId
        protected TblDozentPK tblDozentPK;
        @Size(max = 45)
        @Column(name = "doz_name")
        private String dozName;
        @Size(max = 45)
        @Column(name = "doz_nachname")
        private String dozNachname;
        @Size(max = 45)
        @Column(name = "doz_tel")
        private String dozTel;
        @JoinTable(name = "tbl_Dozent_has_tbl_seminar", joinColumns = {
            @JoinColumn(name = "tbl_Dozent_doz_id", referencedColumnName = "doz_id")}, inverseJoinColumns = {
            @JoinColumn(name = "tbl_seminar_sem_id", referencedColumnName = "sem_id")})
        @ManyToMany
        private Collection<TblSeminar> tblSeminarCollection;
        @JoinColumn(name = "tbl_login_users_login_email", referencedColumnName = "login_email", insertable = false, updatable = false)
        @ManyToOne(optional = false)
        private TblLoginUsers tblLoginUsers;

        public TblDozent() {
        }

        public TblDozent(TblDozentPK tblDozentPK) {
            this.tblDozentPK = tblDozentPK;
        }

        public TblDozent(int dozId, String tblLoginUsersLoginEmail) {
            this.tblDozentPK = new TblDozentPK(dozId, tblLoginUsersLoginEmail);
        }

        public TblDozentPK getTblDozentPK() {
            return tblDozentPK;
        }

        public void setTblDozentPK(TblDozentPK tblDozentPK) {
            this.tblDozentPK = tblDozentPK;
        }

        public String getDozName() {
            return dozName;
        }

        public void setDozName(String dozName) {
            this.dozName = dozName;
        }

        public String getDozNachname() {
            return dozNachname;
        }

        public void setDozNachname(String dozNachname) {
            this.dozNachname = dozNachname;
        }

        public String getDozTel() {
            return dozTel;
        }

        public void setDozTel(String dozTel) {
            this.dozTel = dozTel;
        }

        @XmlTransient
        public Collection<TblSeminar> getTblSeminarCollection() {
            return tblSeminarCollection;
        }

        public void setTblSeminarCollection(Collection<TblSeminar> tblSeminarCollection) {
            this.tblSeminarCollection = tblSeminarCollection;
        }

        public TblLoginUsers getTblLoginUsers() {
            return tblLoginUsers;
        }

        public void setTblLoginUsers(TblLoginUsers tblLoginUsers) {
            this.tblLoginUsers = tblLoginUsers;
        }

        @Override
        public int hashCode() {
            int hash = 0;
            hash += (tblDozentPK != null ? tblDozentPK.hashCode() : 0);
            return hash;
        }

        @Override
        public boolean equals(Object object) {
            // TODO: Warning - this method won't work in the case the id fields are not set
            if (!(object instanceof TblDozent)) {
                return false;
            }
            TblDozent other = (TblDozent) object;
            if ((this.tblDozentPK == null && other.tblDozentPK != null) || (this.tblDozentPK != null && !this.tblDozentPK.equals(other.tblDozentPK))) {
                return false;
            }
            return true;
        }

        @Override
        public String toString() {
            return "entities.TblDozent[ tblDozentPK=" + tblDozentPK + " ]";
        }

    }

     
    Code (Java):



    package entities;

    import java.io.Serializable;
    import javax.persistence.Basic;
    import javax.persistence.Column;
    import javax.persistence.Embeddable;
    import javax.validation.constraints.NotNull;
    import javax.validation.constraints.Size;


    @Embeddable
    public class TblDozentPK implements Serializable {
        @Basic(optional = false)
        @Column(name = "doz_id")
        private int dozId;
        @Basic(optional = false)
        @NotNull
        @Size(min = 1, max = 255)
        @Column(name = "tbl_login_users_login_email")
        private String tblLoginUsersLoginEmail;

        public TblDozentPK() {
        }

        public TblDozentPK(int dozId, String tblLoginUsersLoginEmail) {
            this.dozId = dozId;
            this.tblLoginUsersLoginEmail = tblLoginUsersLoginEmail;
        }

        public int getDozId() {
            return dozId;
        }

        public void setDozId(int dozId) {
            this.dozId = dozId;
        }

        public String getTblLoginUsersLoginEmail() {
            return tblLoginUsersLoginEmail;
        }

        public void setTblLoginUsersLoginEmail(String tblLoginUsersLoginEmail) {
            this.tblLoginUsersLoginEmail = tblLoginUsersLoginEmail;
        }

        @Override
        public int hashCode() {
            int hash = 0;
            hash += (int) dozId;
            hash += (tblLoginUsersLoginEmail != null ? tblLoginUsersLoginEmail.hashCode() : 0);
            return hash;
        }

        @Override
        public boolean equals(Object object) {
            // TODO: Warning - this method won't work in the case the id fields are not set
            if (!(object instanceof TblDozentPK)) {
                return false;
            }
            TblDozentPK other = (TblDozentPK) object;
            if (this.dozId != other.dozId) {
                return false;
            }
            if ((this.tblLoginUsersLoginEmail == null && other.tblLoginUsersLoginEmail != null) || (this.tblLoginUsersLoginEmail != null && !this.tblLoginUsersLoginEmail.equals(other.tblLoginUsersLoginEmail))) {
                return false;
            }
            return true;
        }

        @Override
        public String toString() {
            return "entities.TblDozentPK[ dozId=" + dozId + ", tblLoginUsersLoginEmail=" + tblLoginUsersLoginEmail + " ]";
        }
       
    }

     
     
  2. Vielleicht hilft dir dieser Kurs hier weiter --> (hier klicken)
  3. stg
    stg Bekanntes Mitglied
    Dein Primärschlüssel besteht aus der Dozent-ID und der Email-Adresse. Fürs mapping zwischen Dozent und Seminar verwendest du aber nur die Dozent-ID. Es sollte sich selbst erklären, dass das so nicht funktionieren kann.

    Ein solches Mapping mit zusammengesetzten Schlüsseln habe ich ehrlich gesagt noch nie gemacht. Bei mir haben alle Tabellen immer eine eigene (technische) ID als PK. Wenn ich darauf angewiesen bin, dass wie in deinem Beispiel die Kombination aus DozentID und Email eindeutig sein soll, dann setz ich einfach zusätzlich zu der extra technischen ID noch ein UniqueConstraint auf die entsprechenden Spalten. Das erspart einem beim Mapping definitiv einiges an Kopfzerbrechen, weil man alles auf dem Standardweg lösen kann.
     
  4. Spitfire777
    Spitfire777 Neues Mitglied
    Hi!

    Ich würde es auch mit nur einer ID lösen und den Rest auf Unique setzen. Allerdings hat man dann immer ein ungewünschtes Beziehungsobjekt und das kann bei hochskalierten Anwendungen unter Umständen auch die Performance drücken (ich gehe mal davon aus).

    Hab mit EclipseLink keine Erfahrung und weiß auch nicht gegen welche JPA-Version du implementierst.

    Hier aber ein Beispiel aus meinem J2EE-Vorlesungsskript mit Hibernate:

    Code (Java):
    @Entity
    public class Bestellung {
        ...
        @Id
        private Long id;
        ...

        @ManyToMany
        @JoinTable(name = "bestellung_zu_lieferung",
            joinColumns = @JoinColumn(name = "bestellung_fk"),
            inverseJoinColumns = @JoinColumn(name = "lieferung_fk"))
        private List<lieferungen> lieferungen;

        ...
    }
    Code (Java):
    @Entity
    public class Lieferung {
        ...
        @Id
        private Long id;
        ...

        @ManyToMany
        @JoinTable(name = "bestellung_zu_lieferung",
            joinColumns = @JoinColumn(name = "bestellung_fk"),
            inverseJoinColumns = @JoinColumn(name = "lieferung_fk"))
        private List<Bestellung> bestellungen;

        ...
    }
     
    Zuletzt bearbeitet: 22. Jan. 2014
Die Seite wird geladen...

JPA: Entity Klasse @JoinColumns Problem - Ähnliche Themen

Entity-Klassen generieren
Entity-Klassen generieren im Forum Datenbankprogrammierung
Speicherleck bei Entityklassen
Speicherleck bei Entityklassen im Forum Data Tier
Neues Attribut in Entity-Klasse
Neues Attribut in Entity-Klasse im Forum Datenbankprogrammierung
Entity Verwaltung in einem 2D Spiel
Entity Verwaltung in einem 2D Spiel im Forum Spiele- und Multimedia-Programmierung
API Anbindung letzte Entity bekommen
API Anbindung letzte Entity bekommen im Forum Softwareentwicklung
Thema: JPA: Entity Klasse @JoinColumns Problem