Một cột Lặp lại khác trong ánh xạ cho lỗi thực thể


110

Mặc dù tất cả những người khác đã đăng, tôi không thể tìm thấy giải pháp cho lỗi này với GlassFish, trên 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")

Đây là mã:

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
}

Câu trả lời:


129

Thông báo rõ ràng: bạn có một cột lặp lại trong ánh xạ. Điều đó có nghĩa là bạn đã ánh xạ cùng một cột cơ sở dữ liệu hai lần. Và thực sự, bạn có:

@Column(nullable=false)
private Long customerId;

và cả:

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

(và tương tự với productId/ product).

Bạn không nên tham chiếu đến các thực thể khác bằng ID của họ, nhưng bằng một tham chiếu trực tiếp đến thực thể. Loại bỏ các customerIdlĩnh vực, nó vô ích. Và làm tương tự cho productId. Nếu bạn muốn có ID khách hàng của một lần bán hàng, bạn chỉ cần làm như sau:

sale.getCustomer().getId()

1
Tôi cũng gặp lỗi tương tự, nhưng tình huống của tôi hơi khác một chút. Thực thể của tôi có thể là cha của một hoặc nhiều thực thể cùng loại. Những đứa trẻ có tham chiếu về id của cha chúng cũng như id duy nhất của riêng chúng. Làm cách nào để giải quyết sự phụ thuộc vòng tròn như vậy?
Ciri

@JBNizet Làm cách nào sau đó tôi có thể tiết kiệm Giảm giá với một số cụ thể customerId? (ví dụ: từ JSON).
Mikhail Batcer

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

5
Làm thế nào để bạn xử lý trường hợp bạn có một @EmbeddedIdkhóa tổng hợp giữa customerIdvà một trường khác của Customerlớp? Trong trường hợp này, tôi cần cả hai cột lặp lại trong ánh xạ, đúng không?
louis amoros

2
@louisamoros Vâng, bạn lặp lại nó, nhưng bạn thêm @MapsId("customerId"), xem stackoverflow.com/questions/16775055/hibernate-embeddedid-join
Dalibor Filus

71

Nếu bạn gặp khó khăn với cơ sở dữ liệu kế thừa nơi ai đó đã đặt chú thích JPA nhưng KHÔNG xác định các mối quan hệ và bạn hiện đang cố gắng xác định chúng để sử dụng trong mã của mình, thì bạn có thể KHÔNG xóa được customerId @Column vì mã khác có thể trực tiếp tham khảo nó đã. Trong trường hợp đó, hãy xác định các mối quan hệ như sau:

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

Điều này cho phép bạn truy cập các mối quan hệ. Tuy nhiên, để thêm / cập nhật các mối quan hệ, bạn sẽ phải thao tác trực tiếp với các khóa ngoại thông qua các giá trị @Column được xác định của chúng. Đó không phải là một tình huống lý tưởng, nhưng nếu bạn gặp phải tình huống này, ít nhất bạn có thể xác định các mối quan hệ để có thể sử dụng JPQL thành công.


1
Cảm ơn, đây chính xác là giải pháp tôi cần, ngoài trường ManyToOneánh xạ, tôi cần một trường được ánh xạ trực tiếp đến cột nối.
ryenus

Đây là giải pháp phù hợp khi bạn có một trường chứa khóa và khóa chính cùng một lúc.
AntuanSoft

Oh my god, bạn có thể đã lưu ngày của tôi ... chính xác trường hợp này
Clomez

22

sử dụng cái này, là công việc cho tôi:

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

Cảm ơn, đây chính là giải pháp tôi cần

Hoạt động ngay cả với tùy chọn = 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;
}

Nếu bạn đã ánh xạ một cột và vô tình đặt cùng các giá trị cho têntên tham chiếuColumnName trong chế độ ngủ đông @JoinColumn sẽ gây ra cùng một lỗi ngu ngốc

Lỗi:

Gây ra bởi: org.hibernate.MappingException: Cột lặp lại trong ánh xạ cho cột entity: com.testtest.SomeCustomEntity: COLUMN_NAME (phải được ánh xạ với insert = "false" update = "false")


2
Điểm mấu chốt ở đây đối với tôi là lỗi cho biết "nên được ánh xạ với insert = false update = false" nhưng các tham số / phương thức thực tế phải là "insertable = false, updatable = false".
Cú đêm

1

Hy vọng điều này sẽ giúp ích!

@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

Chú ý chỉ cung cấp 1 setter và getter cho bất kỳ thuộc tính nào. Cách tốt nhất để tiếp cận là viết ra định nghĩa của tất cả các thuộc tính, sau đó sử dụng tiện ích setter và getter tạo eclipse thay vì làm thủ công. Tùy chọn đi kèm khi nhấp chuột phải-> nguồn -> Tạo Getter và Setter.


0

Điều này có nghĩa là bạn đang ánh xạ một cột hai lần trong lớp thực thể của mình. Giải thích bằng một ví dụ ...

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

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

Vấn đề trong đoạn mã trên là chúng tôi đang lặp lại ánh xạ ...

Giải pháp

Vì ánh xạ là một phần quan trọng, bạn không muốn loại bỏ điều đó. Thay vào đó, bạn sẽ loại bỏ

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

Bạn vẫn có thể chuyển giá trị của object1 bằng cách tạo một đối tượng của TableClass và gán giá trị Chuỗi của Object1 trong đó.

Điều này hoạt động 100%. Tôi đã thử nghiệm điều này với cơ sở dữ liệu Postgres và Oracle.


0

Chúng tôi đã giải quyết sự phụ thuộc vòng tròn (Thực thể mẹ-con) bằng cách ánh xạ thực thể con thay vì thực thể mẹ trong Grails 4 (GORM).

Thí dụ:

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]
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.