加入@ManyToOne嵌套在@OneToMany中

时间:2015-12-24 18:06:44

标签: java jpa eclipselink jpql fetching-strategy

我创建了以下实体来管理持久购物车:

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

我注意到同一个ShoppingCartItem中的所有ShoppingCart在单个查询中按预期检索,但@ManyToOne private Item item;字段不在联接中,而且每个ShoppingCartItem都有一个单独的查询发出{1}}以在访问时获取该字段

使用EclipseLink,还有一种方法可以在加入/批量获取Item时获取ShoppingCartItem连接吗?如何更改查询和/或代码?

2 个答案:

答案 0 :(得分:1)

如果您使用的是EclipseLink,可以查看@BatchFetch@JoinFetch注释。

答案 1 :(得分:0)

虽然似乎忽略了带有别名的left join fetch,但我发现这个查询提示可以完成这项任务:

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不再按插入顺序返回。这可能是由于EclipseLink中的一个错误,但我认为它并没有真正受到太大的伤害,因为我实际上只需要在向用户显示购物车时订购商品而不是,例如,当用户登录和商品时在匿名购物车中必须转移到用户购物车。