FetchMode如何在Spring Data JPA中工作 [英] How does the FetchMode work in Spring Data JPA
问题描述
我的项目中有三个模型对象之间存在关系(模型和存储库代码片段在结尾处)。
当我调用 PlaceRepository.findById
它会触发三个select查询:
(sql)
-
SELECT * FROM place p where id = arg
-
SELECT * FROM用户u其中u.id = place.user.id
-
SELECT * FROM city c c上的LEFT OUTER JOIN状态s .woj_id = s.id其中c.id = place.city.id
这是非常不寻常的行为(对我来说),据我在阅读Hibernate文档后可以知道它应该总是使用JOIN查询,当 当我使用 我的目标是拥有一个山姆在所有情况下的行为(总是JOIN或SELECT,尽管JOIN首选)。 模型定义: 城市: 存储库: FetchType.LAZY
改变为<$时,查询没有区别在$ City
当 FetchType.LAZY
更改为 FetchType.EAGER
(使用JOIN查询)时, / p>
CityRepository.findById
抑制触发两个选择时:
SELECT * FROM city c其中id = arg * FROM state s where id = city.state.id
@Entity
@Table(name =place)
public class Place extends Identified {
@Fetch(FetchMode.JOIN)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name =id_user_author)
私人用户作者;
@Fetch(FetchMode.JOIN)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name =area_city_id)
私人城市城市;
// getters and setters
}
@Entity
@Table(name =area_city)
public class City extends Identified {
@Fetch(FetchMode.JOIN)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name =area_woj_id)
私有状态;
// getters and setters
}
PlaceRepository
public interface PlaceRepository扩展JpaRepository< Place,Long>,PlaceRepositoryCustom {
Place findById(int id);
}
UserRepository:
public interface UserRepository扩展JpaRepository< User,Long> {
列表<用户>找到所有();
用户findById(int id);
}
CityRepository:
public interface CityRepository扩展JpaRepository< City,Long> ;, CityRepositoryCustom {
City findById(int id);
我认为Spring Data忽略FetchMode。使用Spring Data时,我总是使用 @NamedEntityGraph
和 @EntityGraph
注解
@Entity
@NamedEntityGraph(name =GroupInfo.detail,
attributeNodes = @NamedAttributeNode(members))
公共类GroupInfo {
//默认获取模式是懒惰的。
@ManyToMany
列表< GroupMember> members = new ArrayList< GroupMember>();
...
}
@Repository
公共接口GroupRepository扩展CrudRepository< GroupInfo,String> {
@EntityGraph(value =GroupInfo.detail,type = EntityGraphType.LOAD)
GroupInfo getByGroupName(String name);
检查文档 here
I do have a relation between three model object in my project (model and repository snippets in the end of the post.
When I call PlaceRepository.findById
it does fire three select queries:
("sql")
SELECT * FROM place p where id = arg
SELECT * FROM user u where u.id = place.user.id
SELECT * FROM city c LEFT OUTER JOIN state s on c.woj_id = s.id where c.id = place.city.id
That's rather unusual behavior (for me). As far as I can tell after reading Hibernate documentation it should always use JOIN queries. There is no difference in the queries when FetchType.LAZY
changed to FetchType.EAGER
in the Place
class (query with additional SELECT), the same for the City
class when FetchType.LAZY
changed to FetchType.EAGER
(query with JOIN).
When I use CityRepository.findById
suppressing fires two selects:
SELECT * FROM city c where id = arg
SELECT * FROM state s where id = city.state.id
My goal is to have a the sam behavior in all situations (either always JOIN or SELECT, JOIN preferred though).
Model definitions:
Place:
@Entity
@Table(name = "place")
public class Place extends Identified {
@Fetch(FetchMode.JOIN)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id_user_author")
private User author;
@Fetch(FetchMode.JOIN)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "area_city_id")
private City city;
//getters and setters
}
City:
@Entity
@Table(name = "area_city")
public class City extends Identified {
@Fetch(FetchMode.JOIN)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "area_woj_id")
private State state;
//getters and setters
}
Repositories:
PlaceRepository
public interface PlaceRepository extends JpaRepository<Place, Long>, PlaceRepositoryCustom {
Place findById(int id);
}
UserRepository:
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findAll();
User findById(int id);
}
CityRepository:
public interface CityRepository extends JpaRepository<City, Long>, CityRepositoryCustom {
City findById(int id);
}
I think that Spring Data ignores the FetchMode. I always use the @NamedEntityGraph
and @EntityGraph
annotations when working with Spring Data
@Entity
@NamedEntityGraph(name = "GroupInfo.detail",
attributeNodes = @NamedAttributeNode("members"))
public class GroupInfo {
// default fetch mode is lazy.
@ManyToMany
List<GroupMember> members = new ArrayList<GroupMember>();
…
}
@Repository
public interface GroupRepository extends CrudRepository<GroupInfo, String> {
@EntityGraph(value = "GroupInfo.detail", type = EntityGraphType.LOAD)
GroupInfo getByGroupName(String name);
}
Check the documentation here
这篇关于FetchMode如何在Spring Data JPA中工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!