如何与具有Hibernate,JPA组合键的不同实体建立一对多关系?

时间:2019-04-18 12:04:31

标签: java hibernate spring-boot jpa

我想为以下关系构建实体类。我想要一个具有复合键的实体ProductWiseCustomer。这些密钥也映射到产品和客户实体。如何达到目的?

Entity Relationship

到目前为止,我已经做了。

Product.java

    @Entity
    @Table(name = "product")
    public class Product {
        @Id
        private Long productId;
        private String productName;
        private Decimal productPrice;

        @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, targetEntity = CustomerProductCompound.class)
        private Set<CustomerProductCompound> customerProductCompound;

        //Constructor
        //Setter-getter
    }

Customer.java

    @Entity
    @Table(name = "customerinfo")
    public class CustomerInfo {
        @Id

        private Long customerId;
        private String customerName;
        private Boolean isActive;

        @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, targetEntity = CustomerProductCompound.class)
        private Set<CustomerProductCompound> customerProductCompound;

   //Constructor
   //Setter-getter
}

CustomerProductCompound.java

    @Embeddable
    public class CustomerProductCompound
   {

        @ManyToOne
        @JoinColumn(name = "customerId")
        private CustomerInfo customerInfo;

        @ManyToOne
        @JoinColumn(name = "productId")
        private Product product;

        //Constructor
        //Setter-getter
    }

运行应用程序时出现以下错误:

使用@OneToMany或@ManyToMany定位未映射的类:com.auth.model.CustomerInfo.customerProductCompound [com.auth.model.CustomerProductCompound]。

2 个答案:

答案 0 :(得分:0)

一种解决方案是使用带有@EmbeddableId的复合标识符。

@Entity
public class ProductWiseCustomer {
    @EmbeddedId
    private ProductCustomerKey key;

}

@Embeddable
public class ProductCustomerKey {

    @ManyToOne(fetch = FetchType.LAZY)
    private Customer customer;

    @ManyToOne(fetch = FetchType.LAZY)
    private Product product;
}

请参阅休眠文档:

https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#identifiers-composite-aggregated

答案 1 :(得分:0)

CustomerProductCompound,仅定义了ProductWiseCustomer的主键。您在CustomerInfoProduct中的集合必须包含ProductWiseCustomer个项目,而不是其键。

@Entity
@Table(name = "product")
public class Product {
    @Id
    private Long productId;
    private String productName;
    private Decimal productPrice;

    @OneToMany(mappedBy = "product", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
    private Set<ProductWiseCustomer> productWiseCustomers;

}

@Entity
@Table(name = "customerinfo")
public class CustomerInfo {
    @Id

    private Long customerId;
    private String customerName;
    private Boolean isActive;

    @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
    private Set<ProductWiseCustomer> productWiseCustomers;

}

注意,我在注释中添加了mappedBy属性。它需要指向引用此对象的另一侧的属性名称。 JPA名称,而不是SQL名称。 targetEntity几乎没有必要,我建议使用orphanRemoval,这样,如果您从集中删除一个,就不必手动删除它。

对于ProductWiseCustomer,您确实需要与模块化编码器显示的密钥相同

@Embeddable
public class ProductCustomerKey {

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "customerId)
    private Customer customer;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "productId")
    private Product product;
}

但是我建议您使用@IdClass而不是@EmbeddedId

@Entity
@IdClass(ProductCustomerKey.class)
public class ProductWiseCustomer {
    @ManyToOne(fetch = FetchType.LAZY) // should be lazy here
    @JoinColumn(name = "customerId)
    private Customer customer;

    @ManyToOne(fetch = FetchType.LAZY) // should be lazy here
    @JoinColumn(name = "productId")
    private Product product;

    private OffsetDateTime createDate;
    private String remarks;
    // getters, setters
}