Une autre colonne répétée dans le mappage pour l'erreur d'entité


112

Malgré tous les autres articles, je ne trouve pas de solution à cette erreur avec GlassFish, sur MacOSX, NetBeans 7.2.

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")

Voici le 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
}

Réponses:


130

Le message est clair: vous avez une colonne répétée dans le mappage. Cela signifie que vous avez mappé deux fois la même colonne de base de données. Et en effet, vous avez:

@Column(nullable=false)
private Long customerId;

et aussi:

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

(et il en va de même pour productId/ product).

Vous ne devez pas référencer d'autres entités par leur ID, mais par une référence directe à l'entité. Supprimez le customerIdchamp, c'est inutile. Et faites de même pour productId. Si vous voulez l'identifiant client d'une vente, il vous suffit de faire ceci:

sale.getCustomer().getId()

1
J'obtiens la même erreur, mais ma situation est un peu différente. Mon entité peut être le père d'une ou plusieurs entités du même type. Les enfants ont une référence sur l'identifiant de leur père ainsi qu'un identifiant unique qui leur est propre. Comment puis-je résoudre une telle dépendance circulaire?
Ciri

@JBNizet Comment puis-je enregistrer une vente avec un particulier customerId? (par exemple à partir de JSON).
Mikhail Batcer

2
Customer customer = entityManager.getReference(customerId, Customer.class); sale.setCustomer(customer);
JB Nizet

5
Comment gérez-vous le cas où vous avez une @EmbeddedIdclé composite entre customerIdet un autre champ de la Customerclasse? Dans ce cas, j'ai besoin des deux colonnes répétées dans le mappage, ai-je raison?
louis amoros

2
@louisamoros Oui, vous le répétez, mais vous ajoutez @MapsId("customerId"), voir stackoverflow.com/questions/16775055/hibernate-embeddedid-join
Dalibor Filus

71

Si vous êtes coincé avec une base de données héritée sur laquelle quelqu'un a déjà placé des annotations JPA mais n'a PAS défini les relations et que vous essayez maintenant de les définir pour les utiliser dans votre code, vous ne pourrez peut-être PAS supprimer le customerId @Column depuis tout autre code peut déjà y faire référence directement. Dans ce cas, définissez les relations comme suit:

@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;

Cela vous permet d'accéder aux relations. Cependant, pour ajouter / mettre à jour les relations, vous devrez manipuler les clés étrangères directement via leurs valeurs @Column définies. Ce n'est pas une situation idéale, mais si vous êtes confronté à ce genre de situation, au moins vous pouvez définir les relations afin que vous puissiez utiliser JPQL avec succès.


1
Merci, c'est exactement la solution dont j'ai besoin, en plus du ManyToOnechamp de mappage, j'ai besoin d'un champ directement mappé à la colonne de jointure.
ryenus

Il s'agit de la bonne solution lorsque vous disposez d'un champ qui transmet la clé primaire et la clé primaire en même temps.
AntuanSoft

Oh mon dieu, vous pourriez avoir sauvé ma journée ... exactement ce cas
Clomez

23

utilisez ceci, c'est du travail pour moi:

@Column(name = "candidate_id", nullable=false)
private Long candidate_id;
@ManyToOne(optional=false)
@JoinColumn(name = "candidate_id", insertable=false, updatable=false)
private Candidate candidate;

Merci, c'est exactement la solution dont j'ai besoin

Fonctionne même avec facultatif = 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;
}

Si vous avez déjà mappé une colonne et avez accidentellement défini les mêmes valeurs pour name et referencedColumnName dans @JoinColumn hibernate donne la même erreur stupide

Erreur:

Causé par: org.hibernate.MappingException: colonne répétée dans le mappage pour l'entité: colonne com.testtest.SomeCustomEntity: COLUMN_NAME (doit être mappée avec insert = "false" update = "false")


2
Un point clé ici pour moi était que l'erreur dit "devrait être mappé avec insert = false update = false" mais les paramètres / méthodes réels devraient être "insertable = false, updatable = false".
Night Owl

1

J'espère que cela aidera!

@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;
    }

0

Veillez à ne fournir qu'un seul setter et getter pour chaque attribut. La meilleure façon d'aborder est d'écrire la définition de tous les attributs, puis d'utiliser l'utilitaire de définition et de lecture eclipse generate plutôt que de le faire manuellement. L'option vient sur clic droit-> source -> Générer Getter et Setter.


0

Cela signifie que vous mappez une colonne deux fois dans votre classe d'entité. Expliquer avec un exemple ...

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

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

Le problème dans l'extrait de code ci-dessus est que nous répétons le mappage ...

Solution

Le mappage étant une partie importante, vous ne souhaitez pas le supprimer. Au lieu de cela, vous supprimerez

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

Vous pouvez toujours transmettre la valeur de object1 en créant un objet de TableClass et en lui attribuant la valeur String d'Object1.

Cela fonctionne à 100%. J'ai testé cela avec Postgres et la base de données Oracle.


0

Nous avons résolu la dépendance circulaire (Entités parent-enfant) en mappant l'entité enfant au lieu de l'entité parente dans Grails 4 (GORM).

Exemple:

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]
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.