Otra columna repetida en la asignación de errores de entidad

110

A pesar de todas las publicaciones de los demás, no puedo encontrar una solución para este error con GlassFish, en 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")

Aquí el código:

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
fuente

Respuestas:

129

El mensaje es claro: tiene una columna repetida en el mapeo. Eso significa que asignó la misma columna de la base de datos dos veces. Y de hecho, tienes:

@Column(nullable=false)
private Long customerId;

y también:

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

(y lo mismo ocurre con productId/product ).

No debe hacer referencia a otras entidades por su ID, sino por una referencia directa a la entidad. Quita el customerIdcampo, es inútil. Y haz lo mismo por productId. Si desea el ID de cliente de una venta, solo necesita hacer esto:

sale.getCustomer().getId()
JB Nizet
fuente
1
Recibo el mismo error, pero mi situación es un poco diferente. Mi entidad puede ser el padre de una o más entidades del mismo tipo. Los niños tienen una referencia sobre la identificación de su padre, así como una identificación única propia. ¿Cómo puedo resolver una dependencia tan circular?
Ciri
@JBNizet ¿Cómo puedo guardar una venta con algún particular customerId? (por ejemplo, de JSON).
Mikhail Batcer
2
Customer customer = entityManager.getReference(customerId, Customer.class); sale.setCustomer(customer);
JB Nizet
5
¿Cómo maneja el caso en el que tiene una @EmbeddedIdclave compuesta entre customerIdy otro campo de la Customerclase? En este caso, necesito ambas columnas repetidas en el mapeo, ¿verdad?
louis amoros
2
@louisamoros Sí, lo repite, pero agrega @MapsId("customerId"), consulte stackoverflow.com/questions/16775055/hibernate-embeddedid-join
Dalibor Filus
71

Si está atascado con una base de datos heredada en la que alguien ya colocó anotaciones JPA pero NO definió las relaciones y ahora está tratando de definirlas para usarlas en su código, entonces es posible que NO pueda eliminar el customerId @Column desde otro código ya puede hacer referencia directamente a él. En ese caso, defina las relaciones de la siguiente manera:

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

Esto le permite acceder a las relaciones. Sin embargo, para agregar / actualizar las relaciones, tendrá que manipular las claves externas directamente a través de sus valores de @Column definidos. No es una situación ideal, pero si se le presenta este tipo de situación, al menos puede definir las relaciones para poder utilizar JPQL con éxito.

Pattmatt
fuente
1
Gracias, esta es exactamente la solución que necesito, además del ManyToOnecampo de mapeo, necesito un campo mapeado directamente a la columna de unión.
ryenus
Esta es la solución correcta cuando tiene un campo que es clave externa y clave primaria al mismo tiempo.
AntuanSoft
Dios mío, podrías haberme salvado el día ... exactamente este caso
Clomez
22

usa esto, es trabajo para mí:

@Column(name = "candidate_id", nullable=false)
private Long candidate_id;
@ManyToOne(optional=false)
@JoinColumn(name = "candidate_id", insertable=false, updatable=false)
private Candidate candidate;
Nomade de Redouane
fuente
Gracias, esta es exactamente la solución que necesito
Funciona incluso con opcional = verdadero.
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 ya ha mapeado una columna y ha establecido accidentalmente los mismos valores para name y referencedColumnName en columna @JoinColumn, hibernación da el mismo error estúpido

Error:

Causado por: org.hibernate.MappingException: columna repetida en el mapeo de la entidad: com.testtest.SomeCustomEntity columna: COLUMN_NAME (debe mapearse con insert = "false" update = "false")

dbow
fuente
2
Un punto clave aquí para mí fue que el error dice "debe ser mapeado con insert = false update = false" pero los parámetros / métodos reales deben ser "insertable = false, Updatable = false".
Night Owl
1

¡Espero que esto ayude!

@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
fuente
0

Tenga cuidado de proporcionar solo 1 setter y getter para cualquier atributo. La mejor manera de acercarse es escribir la definición de todos los atributos y luego usar la utilidad Eclipse generate setter y getter en lugar de hacerlo manualmente. La opción aparece al hacer clic derecho-> fuente -> Generar Getter y Setter.

romil gaurav
fuente
0

Esto significa que está mapeando una columna dos veces en su clase de entidad. Explicando con un ejemplo ...

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

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

El problema en el fragmento de código anterior es que estamos repitiendo el mapeo ...

Solución

Dado que el mapeo es una parte importante, no desea eliminarlo. En cambio, eliminará

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

Aún puede pasar el valor de object1 creando un objeto de TableClass y asignando el valor String de Object1 en él.

Esto funciona al 100%. He probado esto con Postgres y la base de datos Oracle.

Rishabh Agarwal
fuente
0

Hemos resuelto la dependencia circular (entidades padre-hijo) mapeando la entidad secundaria en lugar de la entidad madre en Grails 4 (GORM).

Ejemplo:

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
fuente