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
字段或同时加载 user
和 restaurant
字段急切。这取决于实施情况,无法保证。
参见 this hibernate 的问题。
但据我所知,除了 @NamedEntityGraph
中指定的字段外,Hibernate 仅加载简单的字段,而不加载惰性关联。
所以如果你使用休眠,它应该可以工作。
当然,您需要两个单独的 @NamedEntityGraph
用于 user
和 restaurant
字段。
或者您可以使用 ad-hoc spring-data-jpa
的功能:
@Repository
public interface GroupRepository extends CrudRepository<GroupInfo, String> {
@EntityGraph(attributePaths = { "members" })
GroupInfo getByGroupName(String name);
}
使用此代码,您不再需要显式声明 @NamedEntityGraph
。您可以直接指定内联字段。
新年快乐:)
我有一个使用 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
字段或同时加载 user
和 restaurant
字段急切。这取决于实施情况,无法保证。
参见 this hibernate 的问题。
但据我所知,除了 @NamedEntityGraph
中指定的字段外,Hibernate 仅加载简单的字段,而不加载惰性关联。
所以如果你使用休眠,它应该可以工作。
当然,您需要两个单独的 @NamedEntityGraph
用于 user
和 restaurant
字段。
或者您可以使用 ad-hoc spring-data-jpa
的功能:
@Repository
public interface GroupRepository extends CrudRepository<GroupInfo, String> {
@EntityGraph(attributePaths = { "members" })
GroupInfo getByGroupName(String name);
}
使用此代码,您不再需要显式声明 @NamedEntityGraph
。您可以直接指定内联字段。