Spring DataJPA 中的延迟初始化

Lazy initialization in Spring DataJPA

新年快乐:)

我有一个使用 Hibernate 和 DataJPA 的 Spring MVC 项目。

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "user_id", nullable = false)
private User user;

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "restaurant_id", nullable = false)
@NotNull
private Restaurant restaurant;

如您所见,这里有两个字段使用了 eager fetch。我想让两者都变得懒惰。我需要用户 @NamedEntityGraph 注释,因为我在这里做了:

    @NamedQueries({
    @NamedQuery(name = Restaurant.GET_BY_ID, query = "SELECT r FROM Restaurant r WHERE r.id=?1"),
    })
    @Entity
    @NamedEntityGraph(name = Restaurant.GRAPH_WITH_MENU_HISTORY, attributeNodes = {@NamedAttributeNode("menuHistory")})
    @Table(name = "restaurants")
    public class Restaurant extends NamedEntity {

        @OneToMany(cascade = CascadeType.REMOVE, fetch = FetchType.LAZY, mappedBy = "restaurant")
        @OrderBy(value = "date DESC")
        private List<Dish> menuHistory;

        public static final String GRAPH_WITH_MENU_HISTORY = "Restaurant.withMenuHistory";

我想知道,如果我写

@NamedEntityGraph(name = "G_NAME", attributeNodes = {@NamedAttributeNode("user", "restaurant")})

如果我请求其中之一,第二个会加载吗?还是只会根据请求加载给他?可能是,我需要使用两个图表?

根据 JPA 2.1 规范 3.7.4:

The persistence provider is permitted to fetch additional entity state beyond that specified by a fetch graph or load graph. It is required, however, that the persistence provider fetch all state specified by the fetch or load graph.

所以实际上 @NamedEntityGraph 只是保证了应该急切加载哪些字段,而不是不应该加载哪些字段。

因此,如果您使用 user 创建 @NamedEntityGraph,您的持久性提供程序(例如 Hibernate)只能加载 user 字段或同时加载 userrestaurant 字段急切。这取决于实施情况,无法保证。

参见 this hibernate 的问题。

但据我所知,除了 @NamedEntityGraph 中指定的字段外,Hibernate 仅加载简单的字段,而不加载惰性关联。

所以如果你使用休眠,它应该可以工作。

当然,您需要两个单独的 @NamedEntityGraph 用于 userrestaurant 字段。

或者您可以使用 ad-hoc spring-data-jpa 的功能:

@Repository
public interface GroupRepository extends CrudRepository<GroupInfo, String> {

  @EntityGraph(attributePaths = { "members" })
  GroupInfo getByGroupName(String name);

}

使用此代码,您不再需要显式声明 @NamedEntityGraph。您可以直接指定内联字段。