JPA отношений «многие ко многим» с сущностью

#jpa #orm #mapping #many-to-many

#jpa #orm #сопоставление #многие ко многим

Вопрос:

У меня возникла проблема при попытке создать несколько отношений в JPA с тремя объектами.

  • Порядок
  • Продукт
  • Модификатор

У меня есть объект для обработки отношений «многие ко многим».

  • orderProducts (order_id и product_id) Содержит связь одного заказа, которая может содержать несколько продуктов
  • OrderDetails (order_products_id и modifier_id) Содержит идентификатор предыдущего отношения Order-Products и идентификатор модификатора, который представляет собой набор из нескольких значений, которые могут повлиять на цену продукта.

Не совсем уверен, как обращаться с такого рода отношениями в 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)));

}
 

Приведенный выше запрос мог бы быть лучше, но это даст вам кое-что для работы.