多对多关系 JPA 与实体

Posted

技术标签:

【中文标题】多对多关系 JPA 与实体【英文标题】:Many To Many Relationship JPA with Entity 【发布时间】:2021-05-25 01:04:30 【问题描述】:

我在尝试在 JPA 中与三个实体生成多重关系时遇到问题。

订购 产品 修饰符

我有一个实体来处理多对多的关系。

OrderProducts(order_id 和 product_id) 包含一个订单的关系可以有多个产品 订单详情(order_products_id 和 modifier_id) 包含之前关系 Order-Products 的 id 和修饰符的 Id,修饰符是一组可以影响产品价格的多个值。

不太清楚如何在 JPA 中处理这种关系,因为我是新手。

【问题讨论】:

【参考方案1】:

您需要一个带有复合键的连接实体。您需要进一步研究它。

您的实体:

@Entity
@Table(name = "ordertable")
@Data
public class Order 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @OneToMany(mappedBy = "order")
    @EqualsAndHashCode.Exclude
    private Set<OrderProductModifier> products;
   

@Entity
@Table(name = "product")
@Data
public class Product 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @EqualsAndHashCode.Exclude
    private BigDecimal unitPrice;
  

@Entity
@Table(name = "modifier")
@Data
public class Modifier 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @EqualsAndHashCode.Exclude
    private BigDecimal modifier;

正如您所指出的,将它们联系在一起的实体将需要具有上述每个实体的外键。

@Entity
@Table(name = "orderproductmodifier")
@Data
public class OrderProductModifier 
    @EmbeddedId
    private OrderProductModifierId id;

    @MapsId("orderId")
    @ManyToOne
    @EqualsAndHashCode.Exclude
    @ToString.Exclude
    private Order order;
    
    @MapsId("productId")
    @ManyToOne
    @EqualsAndHashCode.Exclude
    private Product product;

    @MapsId("modifierId")
    @ManyToOne
    @EqualsAndHashCode.Exclude
    private Modifier modifier;

@SuppressWarnings("serial")
@Embeddable
@Data
public class OrderProductModifierId implements Serializable 
    private Long orderId;
    private Long productId;
    private Long modifierId;

这使用起来非常简单:

private void run() 
    EntityManagerFactory factory = Persistence.createEntityManagerFactory("UsersDB");
    EntityManager em = factory.createEntityManager();
     
    em.getTransaction().begin();
    
    Product product = new Product();
    product.setUnitPrice(BigDecimal.TEN);
    em.persist(product);

    Modifier modifier = new Modifier();
    modifier.setModifier(new BigDecimal(".90"));
    em.persist(modifier);

    Order order = new Order();
    em.persist(order);

    OrderProductModifier opm = new OrderProductModifier();
    opm.setId(new OrderProductModifierId());
    opm.setOrder(order);
    opm.setProduct(product);
    opm.setModifier(modifier);
    em.persist(opm);
    
    em.getTransaction().commit();

    em.clear();

    Order o = em.createQuery("select o from Order o join fetch o.products where o.id = 1", Order.class).getSingleResult();
    System.out.println("Order for " + o.getProducts());
    System.out.println("Order cost " + o.getProducts().stream().map(p->p.getProduct().getUnitPrice().multiply(p.getModifier().getModifier()).doubleValue()).collect(Collectors.summingDouble(Double::doubleValue)));


上面的查询可能会更好,但这会给你一些工作。

【讨论】:

以上是关于多对多关系 JPA 与实体的主要内容,如果未能解决你的问题,请参考以下文章

使用 JPA 映射与属性的多对多关系

JPA 与存储在不同数据库中的用户实体的多对多关系

JPA多对多映射

如何在多对多关系上使用休眠和 JPA 删除孤立实体?

JPA - 一个实体如何引用多对多关系中涉及的两个其他实体?

Spring数据JPA-休眠多对多关系在链接实体表中插入null