#java #hibernate #spring-boot #jpa
#java #гибернация #весенняя загрузка #jpa
Вопрос:
Я хочу создать классы сущностей для следующих отношений. Мне нужен объект ProductWiseCustomer, который имеет составной ключ. Эти ключи также сопоставляются с объектами Product и Customer. Как достичь цели?
Пока что я сделал.
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].
Ответ №1:
Одним из решений является использование составного идентификатора с @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;
}
Пожалуйста, ознакомьтесь с документацией hibernate:
Ответ №2:
CustomerProductCompound
поскольку вы определили только первичный ключ ProductWiseCustomer
. Ваши коллекции внутри CustomerInfo
и Product
должны содержать 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
, вам действительно нужен тот же ключ, что и в 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;
}
Но я рекомендую вам использовать @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
}