คอลัมน์ซ้ำอีกคอลัมน์ในการแมปสำหรับข้อผิดพลาดของเอนทิตี


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)

คุณไม่ควรอ้างอิงเอนทิตีอื่นโดยใช้ ID แต่เป็นการอ้างอิงโดยตรงไปยังเอนทิตี ลบcustomerIdฟิลด์ก็ไม่มีประโยชน์ และทำเช่นเดียวกันสำหรับproductId. หากคุณต้องการรหัสลูกค้าของการขายคุณต้องทำสิ่งนี้:

sale.getCustomer().getId()

1
ฉันได้รับข้อผิดพลาดเดียวกัน แต่สถานการณ์ของฉันแตกต่างออกไปเล็กน้อย เอนทิตีของฉันสามารถเป็นบิดาของเอนทิตีประเภทเดียวกันตั้งแต่หนึ่งรายการขึ้นไป เด็ก ๆ มีการอ้างอิงเกี่ยวกับรหัสของพ่อของพวกเขาและรหัสเฉพาะของพวกเขาเอง ฉันจะแก้ไขการพึ่งพาแบบวงกลมดังกล่าวได้อย่างไร
Ciri

@JBNizet ฉันจะบันทึกการขายโดยเฉพาะบางอย่างได้customerIdอย่างไร? (เช่นจาก JSON)
Mikhail Batcer

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

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;

ขอบคุณนี่คือทางออกที่ฉันต้องการ

ใช้งานได้แม้จะมีตัวเลือก = จริง
OndřejStaš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 hibernate โดยไม่ได้ตั้งใจจะให้ข้อผิดพลาดโง่ ๆ เหมือนกัน

ข้อผิดพลาด:

เกิดจาก: org.hibernate.MappingException: คอลัมน์ที่ซ้ำกันในการแม็ปสำหรับเอนทิตี: คอลัมน์ com.testtest.SomeCustomEntity: COLUMN_NAME (ควรแมปด้วย insert = "false" update = "false")


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

0

ดูแลให้เพียง 1 setter และ getter สำหรับแอตทริบิวต์ใด ๆ วิธีที่ดีที่สุดในการเข้าถึงคือการเขียนนิยามของแอ็ตทริบิวต์ทั้งหมดจากนั้นใช้ยูทิลิตี้ eclipse create setter และ getter แทนที่จะทำด้วยตนเอง ตัวเลือกมาเมื่อคลิกขวา -> แหล่งที่มา -> สร้าง Getter และ Setter


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 ได้โดยการสร้าง object ของ TableClass และกำหนดค่า String ของ 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]
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.