我的项目中的三个模型对象之间确实存在关系(帖子末尾的模型和存储库片段。
当我调用 PlaceRepository.findById
时,它会触发三个选择查询:
("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
这是相当不寻常的行为(对我来说)。据我在阅读 Hibernate 文档后所知,它应该始终使用 JOIN 查询。 Place
类中的FetchType.LAZY
改为FetchType.EAGER
后查询没有区别(查询加SELECT),同理当 FetchType.LAZY
更改为 FetchType.EAGER
(使用 JOIN 查询)时的 City
类。
当我使用 CityRepository.findById
抑制触发两个选择时:
SELECT * FROM city c where id = arg
SELECT * FROM state s where id = city.state.id
我的目标是在所有情况下都具有相同的行为(始终 JOIN 或 SELECT,但首选 JOIN)。
模型定义:
地点:
@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
}
城市:
@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
}
存储库:
PlaceRepository
public interface PlaceRepository extends JpaRepository<Place, Long>, PlaceRepositoryCustom {
Place findById(int id);
}
用户存储库:
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findAll();
User findById(int id);
}
城市存储库:
public interface CityRepository extends JpaRepository<City, Long>, CityRepositoryCustom {
City findById(int id);
}
最佳答案
我认为 Spring Data 忽略了 FetchMode。在使用 Spring Data 时,我总是使用 @NamedEntityGraph
和 @EntityGraph
注释
@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);
}
查看文档 here
关于java - Spring Data JPA 中的 FetchMode 是如何工作的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29602386/