Eine weitere wiederholte Spalte in der Zuordnung für Entitätsfehler

110

Trotz aller anderen Beiträge kann ich mit GlassFish unter MacOSX, NetBeans 7.2 keine Lösung für diesen Fehler finden.

Here the error :
SEVERE: Exception while invoking class org.glassfish.persistence.jpa.JPADeployer
prepare method
SEVERE: Exception while preparing the app
SEVERE: [PersistenceUnit: supmarket] Unable to build EntityManagerFactory

...

Caused by: org.hibernate.MappingException: Repeated column in mapping for entity:
com.supmarket.entity.Sale column: customerId
(should be mapped with insert="false" update="false")

Hier der Code:

Sale.java

@Entity
public class Sale {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(nullable=false)
    private Long idFromAgency;

    private float amountSold;

    private String agency;

    @Temporal(javax.persistence.TemporalType.DATE)
    private Date createdate;

    @Column(nullable=false)
    private Long productId;

    @Column(nullable=false)
    private Long customerId;

    @ManyToOne(optional=false)
    @JoinColumn(name="productId",referencedColumnName="id_product")
    private Product product;

    @ManyToOne(optional=false)
    @JoinColumn(name="customerId",referencedColumnName="id_customer")
    private Customer customer;


    public void Sale(){}    
    public void Sale(Long idFromAgency, float amountSold, String agency
            , Date createDate, Long productId, Long customerId){        
        ...
    }

    // then getters/setters
}

Customer.java

@Entity
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="id_customer")
    private Long id_customer;

    @Column(nullable=false)
    private Long idFromAgency;

    private String  gender,
                    maritalState,
                    firstname,
                    lastname,
                    incomeLevel;

    @OneToMany(mappedBy="customer",targetEntity=Sale.class, fetch=FetchType.EAGER)
    private Collection sales;


    public void Customer(){}

    public void Customer(Long idFromAgency, String gender, String maritalState,
            String firstname, String lastname, String incomeLevel) {
        ...
    }

}

Product.java

public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="id_product")
    private Long id_product;

    @Column(nullable=false)
    private Long idFromAgency;

    private String name;

    @OneToMany(mappedBy="product",targetEntity=Sale.class, fetch=FetchType.EAGER)
    private Collection sales;

    //constructors + getters +setters
}
Canardman
quelle

Antworten:

129

Die Nachricht ist klar: Sie haben eine wiederholte Spalte in der Zuordnung. Das heißt, Sie haben dieselbe Datenbankspalte zweimal zugeordnet. Und in der Tat haben Sie:

@Column(nullable=false)
private Long customerId;

und auch:

@ManyToOne(optional=false)
@JoinColumn(name="customerId",referencedColumnName="id_customer")
private Customer customer;

(und das gleiche gilt für productId/ product).

Sie sollten andere Entitäten nicht anhand ihrer ID referenzieren, sondern durch einen direkten Verweis auf die Entität. Entfernen Sie das customerIdFeld, es ist nutzlos. Und mach das gleiche für productId. Wenn Sie die Kunden-ID eines Verkaufs wünschen, müssen Sie nur Folgendes tun:

sale.getCustomer().getId()
JB Nizet
quelle
1
Ich erhalte den gleichen Fehler, aber meine Situation ist etwas anders. Meine Entität kann der Vater einer oder mehrerer Entitäten desselben Typs sein. Die Kinder haben einen Hinweis auf den Ausweis ihres Vaters sowie einen eigenen Ausweis. Wie kann ich eine solche zirkuläre Abhängigkeit auflösen?
Ciri
@JBNizet Wie kann ich dann einen Verkauf mit einem bestimmten speicherncustomerId ? (zB von JSON).
Mikhail Batcer
2
Customer customer = entityManager.getReference(customerId, Customer.class); sale.setCustomer(customer);
JB Nizet
5
Wie gehen Sie mit dem Fall um, in dem Sie einen @EmbeddedIdzusammengesetzten Schlüssel zwischen customerIdund einem anderen Feld der CustomerKlasse haben? In diesem Fall brauche ich beide wiederholten Spalten in der Zuordnung, habe ich Recht?
Louis Amoros
2
@ Louisamoros Ja, Sie wiederholen es, aber Sie fügen hinzu @MapsId("customerId"), siehe stackoverflow.com/questions/16775055/hibernate-embeddedid-join
Dalibor Filus
71

Wenn Sie mit einer Legacy-Datenbank nicht weiterkommen, in der bereits jemand JPA-Anmerkungen platziert hat, die Beziehungen jedoch NICHT definiert hat und Sie nun versuchen, sie für die Verwendung in Ihrem Code zu definieren, können Sie die customerId @Column möglicherweise NICHT seit anderem Code löschen kann bereits direkt darauf verweisen. Definieren Sie in diesem Fall die Beziehungen wie folgt:

@ManyToOne(optional=false)
@JoinColumn(name="productId",referencedColumnName="id_product", insertable=false, updatable=false)
private Product product;

@ManyToOne(optional=false)
@JoinColumn(name="customerId",referencedColumnName="id_customer", insertable=false, updatable=false)
private Customer customer;

Auf diese Weise können Sie auf die Beziehungen zugreifen. Um die Beziehungen hinzuzufügen / zu aktualisieren, müssen Sie die Fremdschlüssel jedoch direkt über ihre definierten @ Column-Werte bearbeiten. Es ist keine ideale Situation, aber wenn Sie diese Art von Situation erhalten, können Sie zumindest die Beziehungen definieren, damit Sie JPQL erfolgreich verwenden können.

pattmatt
quelle
1
Vielen Dank, dies ist genau die Lösung, die ich brauche. Neben dem ManyToOneZuordnungsfeld benötige ich ein Feld, das direkt der Join-Spalte zugeordnet ist.
Ryenus
Dies ist die richtige Lösung, wenn Sie ein Feld haben, in dem gleichzeitig Schlüssel und Primärschlüssel angezeigt werden.
AntuanSoft
Oh mein Gott, vielleicht hast du meinen Tag gerettet ... genau in diesem Fall
Clomez
22

benutze dies, ist Arbeit für mich:

@Column(name = "candidate_id", nullable=false)
private Long candidate_id;
@ManyToOne(optional=false)
@JoinColumn(name = "candidate_id", insertable=false, updatable=false)
private Candidate candidate;
Redouane Nomade
quelle
Danke, das ist genau die Lösung, die ich brauche
Funktioniert auch mit optional = true.
Ondřej Stašek
11
@Id
@Column(name = "COLUMN_NAME", nullable = false)
public Long getId() {
    return id;
}

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, targetEntity = SomeCustomEntity.class)
@JoinColumn(name = "COLUMN_NAME", referencedColumnName = "COLUMN_NAME", nullable = false, updatable = false, insertable = false)
@org.hibernate.annotations.Cascade(value = org.hibernate.annotations.CascadeType.ALL)
public List<SomeCustomEntity> getAbschreibareAustattungen() {
    return abschreibareAustattungen;
}

Wenn Sie bereits eine Spalte zugeordnet haben und versehentlich dieselben Werte für name und referencedColumnName in @JoinColumn Hibernate festgelegt haben, wird derselbe dumme Fehler ausgegeben

Error:

Auslöser: org.hibernate.MappingException: Wiederholte Spalte in der Zuordnung für Entität: com.testtest.SomeCustomEntity Spalte: COLUMN_NAME (sollte mit insert = "false" update = "false" zugeordnet werden)

dbow
quelle
2
Ein wichtiger Punkt für mich war, dass der Fehler lautet "sollte mit insert = false update = false zugeordnet werden", aber die tatsächlichen Parameter / Methoden sollten "insertable = false, updatable = false" sein.
Night Owl
1

Hoffe das wird helfen!

@OneToOne(optional = false)
    @JoinColumn(name = "department_id", insertable = false, updatable = false)
    @JsonManagedReference
    private Department department;

@JsonIgnore
    public Department getDepartment() {
        return department;
    }

@OneToOne(mappedBy = "department")
private Designation designation;

@JsonIgnore
    public Designation getDesignation() {
        return designation;
    }
Multi Cabz
quelle
0

Achten Sie darauf, für jedes Attribut nur 1 Setter und Getter bereitzustellen. Der beste Weg, dies zu erreichen, besteht darin, die Definition aller Attribute aufzuschreiben und dann das Dienstprogramm eclipse generate setter und getter zu verwenden, anstatt es manuell auszuführen. Die Option ist Rechtsklick-> Quelle -> Getter und Setter generieren.

Romil Gaurav
quelle
0

Dies bedeutet, dass Sie eine Spalte in Ihrer Entitätsklasse zweimal zuordnen. Mit einem Beispiel erklären ...

    @Column(name = "column1")
    private String object1;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "column1", referencedColumnName = "column1")
    private TableClass object2;

Das Problem im obigen Code-Snippet ist, dass wir das Mapping wiederholen ...

Lösung

Da das Mapping ein wichtiger Teil ist, möchten Sie das nicht entfernen. Stattdessen werden Sie entfernen

    @Column(name = "column1")
    private String uniqueId;

Sie können den Wert von object1 weiterhin übergeben, indem Sie ein Objekt von TableClass erstellen und den String-Wert von Object1 darin zuweisen.

Dies funktioniert zu 100%. Ich habe dies mit Postgres und Oracle Datenbank getestet.

Rishabh Agarwal
quelle
0

Wir haben die zirkuläre Abhängigkeit (Eltern-Kind-Entitäten) gelöst, indem wir die untergeordnete Entität anstelle der übergeordneten Entität in Grails 4 (GORM) zugeordnet haben.

Beispiel:

Class Person {
    String name
}

Class Employee extends Person{
    String empId
}

//Before my code 
Class Address {
    static belongsTo = [person: Person]
}

//We changed our Address class to:
Class Address {
    static belongsTo = [person: Employee]
}
Vinitha Pukazh Bagya R.
quelle