加入获取嵌套在 @OneToMany 中的 @ManyToOne
Posted
技术标签:
【中文标题】加入获取嵌套在 @OneToMany 中的 @ManyToOne【英文标题】:Join fetching @ManyToOne nested inside @OneToMany 【发布时间】:2016-03-31 02:42:20 【问题描述】:我创建了以下实体来管理持久购物车:
ShoppingCart.java:
@Entity
public class ShoppingCart
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@PrivateOwned
@OneToMany(mappedBy = "cart", cascade = CascadeType.ALL)
@OrderBy("creationTimestamp")
private List<ShoppingCartItem> items;
public ShoppingCart()
// Getters and setters...
ShoppingCartItem.java:
@Entity
@IdClass(ShoppingCartItemId.class)
public class ShoppingCartItem
@Id
@ManyToOne
private Item item;
@Id
@ManyToOne
private ShoppingCart cart;
private int quantity;
@Column(precision = 17, scale = 2)
private BigDecimal price;
@Temporal(TemporalType.TIMESTAMP)
private Date creationTimestamp;
protected ShoppingCartItem()
@PrePersist
protected void prePersist()
creationTimestamp = new Date();
public ShoppingCartItem(ShoppingCart cart, Item item, int quantity)
this.cart = cart;
this.item = item;
this.quantity = quantity;
this.price = item.getPrice();
// Getters and setters...
Item.java:
@Entity
public class Item
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
private Brand brand;
private String model;
private String variant;
private String description;
@Column(precision = 17, scale = 2)
private BigDecimal price;
private int availability;
protected Item()
// Constructors, getters and setters...
当我发出以下 JPQL 查询时:
SELECT c FROM ShoppingCart c JOIN FETCH c.items WHERE c.id = :id
我注意到同一个 ShoppingCart
中的所有 ShoppingCartItem
s 在单个查询中按预期检索,但 @ManyToOne private Item item;
字段不在连接中,并且针对每个 ShoppingCartItem
发出单独的查询以获取该字段访问时。
使用 EclipseLink,有没有办法在连接/批量获取 ShoppingCartItem
s 时也获取 Item
s 连接?如何更改查询和/或代码?
【问题讨论】:
【参考方案1】:如果您使用的是 EclipseLink,您可以查看 @BatchFetch 和 @JoinFetch 注释。
【讨论】:
但是当使用 JPA 并且 JPA 处理可用时,这样做是不明智的(并丢弃可移植性) 是的,确实如此,但问题包含术语“使用 EclipseLink,有没有办法”,并且使用注释比使用基于字符串的 JPQL 或标准查询更简单且不易出错。也许还使用了 EclipseLink 的其他专有特性。【参考方案2】:虽然带有别名的 left join fetch
s 似乎被忽略了,但我发现这个查询提示可以完成这项工作:
Query query = entityManager.createQuery("SELECT c FROM ShoppingCart c WHERE c.id = :id");
query.setHint("eclipselink.left-join-fetch", "c.items.item.brand");
这可能比注释方法更好,因为它可以为每个查询指定。
更新
使用此提示破坏了@OrderBy("creationTimestamp")
,因此ShoppingCartItem
s 不再按插入顺序返回。这可能是由于 EclipseLink 中的一个错误,但我认为它并没有太大的伤害,因为我实际上只需要在向用户显示购物车时订购商品,而不是在用户登录和商品时订购商品在匿名购物车中必须转移到用户购物车。
【讨论】:
以上是关于加入获取嵌套在 @OneToMany 中的 @ManyToOne的主要内容,如果未能解决你的问题,请参考以下文章
Spring boot JPA - 没有嵌套对象的 JSON 与 OneToMany 关系