Ще один стовпчик, що повторюється, у відображенні помилок сутності


111

Незважаючи на всі інші публікації, я не можу знайти рішення для цієї помилки у 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")

Ось код:

Продаж.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()

1
Я отримую ту ж помилку, але моя ситуація дещо інша. Моя сутність може бути батьком однієї або декількох сутностей одного типу. Діти мають посилання на ідентифікацію свого батька, а також унікальний власний ідентифікатор. Як я можу вирішити таку кругову залежність?
Чірі

@JBNizet Як я можу зберегти Продаж з певним customerId? (наприклад, від JSON).
Михайло Батцер

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

5
Як ви поводитесь із випадком, коли у вас є @EmbeddedIdскладений ключ між customerIdта іншим полем Customerкласу? У цьому випадку мені потрібні обидва повторні стовпці в картографуванні, я прав?
louis amoros

2
@louisamoros Так, ви повторити його, але ви додасте @MapsId("customerId")см stackoverflow.com/questions/16775055/hibernate-embeddedid-join
Dalibor Filus

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

Боже мій, ти міг врятувати мій день ... саме цей випадок
Clomez

22

використовувати це, це робота для мене:

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

Дякую, саме це мені потрібне рішення

Працює навіть із необов'язковим = 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;
}

Якщо ви вже намітили стовпець і випадково встановили однакові значення для імені та referencedColumnName в @JoinColumn в сплячому режимі дає ту саму дурну помилку

Помилка:

Викликано: org.hibernate.MappingException: Повторний стовпець у картографічному відображенні для сутності: com.testtest.SomeCustomEntity стовпець: COLUMN_NAME (має бути відображено вставкою = "false" update = "false")


2
Ключовим моментом для мене було те, що помилка говорить, що "має бути відображено вставкою = помилкове оновлення = помилково", але фактичні параметри / методи повинні бути "вставними = помилковими, оновленнями = помилковими".
Сова

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

0

Подбайте про те, щоб надати лише 1 сетер та будь-який атрибут для будь-якого атрибуту. Найкращий спосіб наблизитись до запису визначення всіх атрибутів, а потім використовувати утиліту генератора затемнення та утиліту, а не робити це вручну. Опція доступна правою кнопкою миші -> джерело -> Створити гетьтер та сетер.


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 і призначити в ньому значення String Object1.

Це працює на 100%. Я перевірив це за допомогою бази даних Postgres та Oracle.


0

Ми вирішили циркулярну залежність (батьківські і дочірні сутності), зіставивши дочірнє утворення замість материнської сутності у Граалі 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]
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.