简体   繁体   中英

How to build one to many relationship with different entities which have a composite key with Hibernate, JPA?

I want to build entity classes for the following relationship. I want an entity ProductWiseCustomer which has a composite key. Those key also mapped with Product and Customer entities. How to achieve the purpose?

实体关系

So far what I have done.

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
    }

While running the application getting the following error:

Use of @OneToMany or @ManyToMany targeting an unmapped class: com.auth.model.CustomerInfo.customerProductCompound[com.auth.model.CustomerProductCompound].

One solution is to use a composite identifier with @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;
}

Please see the hibernate documentation:

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

CustomerProductCompound as you have defined just the primary key of ProductWiseCustomer . Your collections inside CustomerInfo and Product must contain ProductWiseCustomer items, not its key.

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

}

Notice I added the mappedBy property in the annotations. It needs to point to the property name on the other side that refers to this object. The JPA name, not the SQL name. targetEntity is rarely necessary, and I've suggested orphanRemoval , so that if you remove one from the set, you don't have to manually delete it for it to go away.

As for the ProductWiseCustomer , you do need the same key as shown by Modular Coder

@Embeddable
public class ProductCustomerKey {

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

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

But I recommend you use @IdClass instead of @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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM