Sir*_*eta 74 java spring hibernate jpa spring-data-jpa
我确实在我的项目中有三个模型对象之间的关系(帖子末尾的模型和存储库片段).
当我打电话时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查询.在类中FetchType.LAZY
更改为 查询(使用附加SELECT 查询)时,查询没有区别,更改为 (使用JOIN查询)时类相同.FetchType.EAGER
Place
City
FetchType.LAZY
FetchType.EAGER
当我使用CityRepository.findById
抑制火时两个选择:
SELECT * FROM city c where id = arg
SELECT * FROM state s where id = city.state.id
我的目标是在所有情况下都有一个sam行为(总是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
}
Run Code Online (Sandbox Code Playgroud)
市:
@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
}
Run Code Online (Sandbox Code Playgroud)
库:
PlaceRepository
public interface PlaceRepository extends JpaRepository<Place, Long>, PlaceRepositoryCustom {
Place findById(int id);
}
Run Code Online (Sandbox Code Playgroud)
UserRepository:
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findAll();
User findById(int id);
}
Run Code Online (Sandbox Code Playgroud)
CityRepository:
public interface CityRepository extends JpaRepository<City, Long>, CityRepositoryCustom {
City findById(int id);
}
Run Code Online (Sandbox Code Playgroud)
小智 92
我认为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);
}
Run Code Online (Sandbox Code Playgroud)
请查看此处的文档
Vla*_*cea 43
首先,@Fetch(FetchMode.JOIN)
并且@ManyToOne(fetch = FetchType.LAZY)
是对立的,一个指示EAGER取出,而另一个指示LAZY取.
渴望获取很少是一个很好的选择,对于可预测的行为,最好使用query-time JOIN FETCH
指令:
public interface PlaceRepository extends JpaRepository<Place, Long>, PlaceRepositoryCustom {
@Query(value = "SELECT p FROM Place p LEFT JOIN FETCH p.author LEFT JOIN FETCH p.city c LEFT JOIN FETCH c.state where p.id = :id")
Place findById(@Param("id") int id);
}
public interface CityRepository extends JpaRepository<City, Long>, CityRepositoryCustom {
@Query(value = "SELECT c FROM City c LEFT JOIN FETCH c.state where c.id = :id")
City findById(@Param("id") int id);
}
Run Code Online (Sandbox Code Playgroud)
dre*_*619 17
Spring-jpa使用实体管理器创建查询,如果查询是由实体管理器构建的,Hibernate将忽略获取模式.
以下是我使用的工作:
覆盖方法getQuery(Specification<T> spec, Sort sort)
:
@Override
protected TypedQuery<T> getQuery(Specification<T> spec, Sort sort) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<T> query = builder.createQuery(getDomainClass());
Root<T> root = applySpecificationToCriteria(spec, query);
query.select(root);
applyFetchMode(root);
if (sort != null) {
query.orderBy(toOrders(sort, root, builder));
}
return applyRepositoryMethodMetadata(entityManager.createQuery(query));
}
Run Code Online (Sandbox Code Playgroud)
在方法的中间,添加applyFetchMode(root);
以应用获取模式,以使Hibernate使用正确的连接创建查询.
(不幸的是,我们需要从基类复制整个方法和相关的私有方法,因为没有其他扩展点.)
实施applyFetchMode
:
private void applyFetchMode(Root<T> root) {
for (Field field : getDomainClass().getDeclaredFields()) {
Fetch fetch = field.getAnnotation(Fetch.class);
if (fetch != null && fetch.value() == FetchMode.JOIN) {
root.fetch(field.getName(), JoinType.LEFT);
}
}
}
Run Code Online (Sandbox Code Playgroud) 归档时间: |
|
查看次数: |
82289 次 |
最近记录: |