Другой повторяющийся столбец в сопоставлении для ошибки объекта

112

Несмотря на все остальные сообщения, я не могу найти решение этой ошибки в GlassFish на 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")

Вот код:

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
}
слуга
источник

Ответы:

130

Сообщение ясное: у вас есть повторяющийся столбец в сопоставлении. Это означает, что вы дважды сопоставили один и тот же столбец базы данных. И действительно, у вас есть:

@Column(nullable=false)
private Long customerId;

а также:

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

(и то же самое для productId/ product).

Вы не должны ссылаться на другие объекты по их идентификаторам, а должны ссылаться на них напрямую. Убрать customerIdполе, бесполезно. И сделайте то же самое для productId. Если вам нужен идентификатор клиента для продажи, вам просто нужно сделать это:

sale.getCustomer().getId()
JB Nizet
источник
1
Я получаю ту же ошибку, но моя ситуация немного другая. Моя сущность может быть отцом одной или нескольких сущностей одного типа. У детей есть ссылка на идентификатор их отца, а также собственный уникальный идентификатор. Как я могу разрешить такую ​​циклическую зависимость?
Ciri
@JBNizet Как тогда я могу сохранить распродажу с помощью какой-то детали customerId? (например, из JSON).
Михаил Батцер
2
Customer customer = entityManager.getReference(customerId, Customer.class); sale.setCustomer(customer);
JB Nizet
5
Как вы справляетесь со случаем, когда у вас есть @EmbeddedIdсоставной ключ между customerIdи другим полем Customerкласса? В этом случае мне нужны оба повторяющихся столбца в сопоставлении, я прав?
Луис Аморос
2
@louisamoros Да, вы повторяете это, но добавляете @MapsId("customerId"), см. stackoverflow.com/questions/16775055/hibernate-embeddedid-join
Далибор Филус
71

Если вы застряли в устаревшей базе данных, где кто-то уже разместил аннотации JPA, но НЕ определил отношения, и теперь вы пытаетесь определить их для использования в своем коде, то вы НЕ сможете удалить customerId @Column, поскольку другой код может прямо ссылаться на него уже. В этом случае определите отношения следующим образом:

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

Это позволяет вам получить доступ к отношениям. Однако для добавления / обновления отношений вам придется напрямую управлять внешними ключами через их определенные значения @Column. Это не идеальная ситуация, но если вам попадается такая ситуация, по крайней мере, вы можете определить отношения, чтобы успешно использовать JPQL.

Паттматт
источник
1
Спасибо, это именно то решение, которое мне нужно, помимо ManyToOneполя сопоставления мне нужно поле, напрямую сопоставленное со столбцом соединения.
ryenus
Это правильное решение, если у вас есть поле, которое одновременно является внешним ключом и первичным ключом.
AntuanSoft 06
Боже мой, ты мог бы спасти мне день ... именно этот случай
Clomez
23

используйте это, это работа для меня:

@Column(name = "candidate_id", nullable=false)
private Long candidate_id;
@ManyToOne(optional=false)
@JoinColumn(name = "candidate_id", insertable=false, updatable=false)
private Candidate candidate;
Редуанский кочевник
источник
Спасибо, это именно то решение, которое мне нужно
Работает даже с 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;
}

Если вы уже сопоставили столбец и случайно установили одинаковые значения для name и referencedColumnName в @JoinColumn, спящий режим дает ту же глупую ошибку

Ошибка:

Вызвано: org.hibernate.MappingException: повторяющийся столбец в сопоставлении для объекта: com.testtest.SomeCustomEntity столбец: COLUMN_NAME (должен отображаться с помощью insert = "false" update = "false")

dbow
источник
2
Ключевым моментом здесь для меня было то, что в сообщении об ошибке говорится: «должно отображаться с помощью insert = false update = false», но фактические параметры / методы должны быть «insertable = false, updatable = false».
Night Owl
1

Надеюсь, это поможет!

@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
источник
0

Позаботьтесь о том, чтобы для любого атрибута был предоставлен только один метод установки и получения. Лучший способ приблизиться - записать определение всех атрибутов, а затем использовать утилиту eclipse generate setter и getter, а не делать это вручную. Опция появляется при щелчке правой кнопкой мыши -> источник -> Создать получатель и сеттер.

Ромил Гарав
источник
0

Это означает, что вы дважды сопоставляете столбец в своем классе сущности. Объясняя на примере ...

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

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

Проблема в приведенном выше фрагменте кода в том, что мы повторяем сопоставление ...

Решение

Поскольку отображение является важной частью, вы не хотите удалять это. Вместо этого вы удалите

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

Вы по-прежнему можете передать значение object1, создав объект TableClass и присвоив ему строковое значение Object1.

Это работает на 100%. Я тестировал это с помощью Postgres и базы данных Oracle.

Ришаб Агарвал
источник
0

Мы разрешили циклическую зависимость (родительско-дочерние сущности) путем сопоставления дочерней сущности вместо родительской в ​​Grails 4 (GORM).

Пример:

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]
}
Винита Пукаж Багья Р
источник