J2EE实体中的深度负载

时间:2015-11-05 11:54:24

标签: java java-ee jpa jta

我使用EJB应用程序在我的J2EE中有一个3层模型:Cart,它有许多LineItems,每个都有很多书(Book不一定是指一个Line Item,它不是双向的)。

Cart(1) <--> (M) LineItem (1) --> (M) Book 

我希望所有人都渴望加载,即当我提取购物车时,它还应加载所有行项目和所有这些书籍,只需最少的SQL查询(我使用关系数据库,例如MySQL )。它可以使用3个查询完成,每个查询对应一种类型。设置&#34; FetchType.EAGER&#34;导致所有对象被加载,但它有&#34; 2 + n&#34;调用:1对购物车的查询(显然),对行项目的另一个查询,但后来不得不对书籍进行n次查询,其中n是行项目的数量。

我曾经使用Ruby on Rails,使用eager load(使用includes)可以满足我的需要。我也可以用J2EE吗?

(注意:加入可能是一个选项,但我希望从查询中自动填充实体,尽管我认为连接不太舒服)。

我的代码示例:

@Entity
public class Cart implements Serializable {
    @OneToMany(cascade=ALL, mappedBy="cart", fetch = FetchType.EAGER)
    private List<LineItem> lineItems;
}

@Entity
public class LineItem implements Serializable {
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="cart_id", referencedColumnName = "id")
    private Cart cart;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name="book_id", referencedColumnName = "id")
    private Book book;
}

@Entity
public class Book implements Serializable {
   ...
}

以下是购物车有3个行项目的SQL查询示例:

SELECT id, name FROM carts WHERE (id = 19)
SELECT id, quantity, book_id, cart_id FROM line_items WHERE (cart_id = 19)
SELECT id, description, name, price FROM books WHERE (id = 4)
SELECT id, description, name, price FROM books WHERE (id = 3)
SELECT id, description, name, price FROM books WHERE (id = 1)

1 个答案:

答案 0 :(得分:1)

标准JPA提供了join fetch,它标记了一个急切获取的关系,就好像它是通过注释标记的那样。在您的情况下,只需要join fetch lineItems,因为book会在单个查询中急切地加载每个LineItem

使用JPA 2.1,您可以使用Entity graph - 您不需要修改查询,只需在查询中附加一个描述符,用于定义应该急切获取哪些关系。

如果要优化可能的最小查询量,可能需要使用某些JPa提供程序中提供的batch fetching。但要注意,没有标准化的方法来启用它 - 我只是链接到如何使用EclipseLink。