这实际上是一个好问题,值得一些研究和试验。有许多方法可以进行映射。提出更好的设计实际上取决于您的应用程序需求。但是我认为这是实现映射的有效方法:
我有3个独立的实体
Order,
Product和
Address。
我们不会在2个实体
Order和之间实现通常的多对多关系
Product,因为双方之间都有彼此的集合。相反,我会创造另一个实体代表之间的关系
Order,并
Product和让我们命名它
ProductOrder。它们的关系映射如下:
Order
与有着一对多的关系ProductOrder
。ProductOrder
与有着多对一的关系Order
。Product
与有着一对多的关系ProductOrder
。ProductOrder
与有着多对一的关系Product
。
ProductOrder的主键将由
Order和的主键组成
Product-因此这将是一个复合键。因此,我们将需要使用
@IdClass映射复合键。
现在,这是在多对多关系中实现多对多的窍门:
ProductOrder与有着多对多的关系
Address。
请参阅上述每个实体的示例代码:
订单实体
@Entity@Table(name = "ORDERS")public class Order { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "ORDER_ID") private Long id; private int quantity; @oneToMany(mappedBy = "order") private List<ProductOrder> productOrderList = new ArrayList<ProductOrder>();...}产品实体
@Entity@Table(name="PRODUCT")public class Product { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "PRODUCT_ID") private Long id; private String name; @oneToMany(mappedBy = "product") private List<ProductOrder> productOrderList = new ArrayList<ProductOrder>();...}地址实体
@Entity@Table(name="ADDRESS")public class Address { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "ADDRESS_ID") private Long id; private String state; @ManyToMany(mappedBy = "addressList") private List<ProductOrder> productOrderList = new ArrayList<ProductOrder>();...}生产者实体
@Entity@Table(name="PRODUCT_ORDER")@IdClass(ProductOrderId.class)public class ProductOrder { @Id @ManyToOne @JoinColumn(name="ORDER_ID") private Order order; @Id @ManyToOne @JoinColumn(name="PRODUCT_ID") private Product product; @ManyToMany @JoinTable(name="PRODUCT_ORDER_ADDRESS", joinColumns={@JoinColumn(name="ORDER_ID", referencedColumnName="ORDER_ID"), @JoinColumn(name="PRODUCT_ID", referencedColumnName="PRODUCT_ID")}, inverseJoinColumns=@JoinColumn(name="ADDRESS_ID", referencedColumnName="ADDRESS_ID")) private List<Address> addressList = new ArrayList<Address>();...}ProductOrder实体的@IdClass
public class ProductOrderId { private Long order; private Long product;...}以下是用于创建实体并将其持久化的示例代码:
EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Order order = new Order(); order.setQuantity(10); em.persist(order); Product product = new Product(); product.setName("Coffee"); em.persist(product); Address address = new Address(); address.setState("CA"); em.persist(address); ProductOrder productOrder = new ProductOrder(); productOrder.setOrder(order); productOrder.setProduct(product); productOrder.getAddressList().add(address); address.getProductOrderList().add(productOrder); em.persist(productOrder); em.getTransaction().commit();这是在MySQL数据库中生成模式的方式:
Hibernate: create table ADDRESS ( ADDRESS_ID bigint not null auto_increment, state varchar(255), primary key (ADDRESS_ID) )Hibernate: create table ORDERS ( ORDER_ID bigint not null auto_increment, quantity integer not null, primary key (ORDER_ID) )Hibernate: create table PRODUCT ( PRODUCT_ID bigint not null auto_increment, name varchar(255), primary key (PRODUCT_ID) )Hibernate: create table PRODUCT_ORDER ( ORDER_ID bigint, PRODUCT_ID bigint, primary key (ORDER_ID, PRODUCT_ID) )Hibernate: create table PRODUCT_ORDER_ADDRESS ( ORDER_ID bigint not null, PRODUCT_ID bigint not null, ADDRESS_ID bigint not null )Hibernate: alter table PRODUCT_ORDER add constraint FK_sl39bwx60xjbvoiujpaes74ty foreign key (ORDER_ID) references ORDERS (ORDER_ID)Hibernate: alter table PRODUCT_ORDER add constraint FK_n0i7uxq6rxsc0mcred1cds4m9 foreign key (PRODUCT_ID) references PRODUCT (PRODUCT_ID)Hibernate: alter table PRODUCT_ORDER_ADDRESS add constraint FK_kad6crei9lgrv1nuuuff42vs8 foreign key (ADDRESS_ID) references ADDRESS (ADDRESS_ID)Hibernate: alter table PRODUCT_ORDER_ADDRESS add constraint FK_hpx0e467dvpqi5i6kxmujns2b foreign key (ORDER_ID, PRODUCT_ID) references PRODUCT_ORDER (ORDER_ID, PRODUCT_ID)



