如何在Query DSL 4中使用JPA 2.1的loadgraph与fetchgraph
在QueryDSL 4中使用JPA 2.1的LoadGraph和FetchGraph(适配你的环境)
嘿,刚好你的技术栈完全支持JPA 2.1的EntityGraph特性,下面我一步步教你怎么在QueryDSL 4里用LoadGraph和FetchGraph来优化关联数据的加载:
一、先明确两个Graph的核心区别
先快速理清楚,避免用错:
- FetchGraph:严格只加载你指定的属性,不管实体类里默认是
EAGER还是LAZY,未指定的属性全都会延迟加载。 - LoadGraph:加载你指定的属性,同时保留实体类中标记为
EAGER的属性的默认加载策略,未指定且默认是LAZY的属性仍然延迟加载。
二、两种使用方式:命名EntityGraph & 动态EntityGraph
方式1:先定义命名EntityGraph(推荐复用场景)
在你的实体类上用@NamedEntityGraph注解定义好要加载的关联属性,比如你的User实体:
@Getter @DynamicUpdate @Entity @Table(name = "t_user") // 定义命名EntityGraph:加载User的roles关联属性 @NamedEntityGraph( name = "User.withRoles", attributeNodes = @NamedAttributeNode("roles") ) public class User { @Id private Long id; private String username; @OneToMany(mappedBy = "user", fetch = FetchType.LAZY) private List<Role> roles; // 其他字段... }
然后在QueryDSL查询中调用这个命名Graph:
// 注入EntityManager(Spring环境下直接@Autowired即可) @Autowired private EntityManager entityManager; public List<User> getUsersWithRoles() { JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager); QUser qUser = QUser.user; // 获取命名的EntityGraph EntityGraph<?> fetchGraph = entityManager.getEntityGraph("User.withRoles"); // 构建查询并设置Hint:用FetchGraph就指定"javax.persistence.fetchgraph" List<User> users = queryFactory.selectFrom(qUser) .where(qUser.username.like("%test%")) .setHint("javax.persistence.fetchgraph", fetchGraph) // 如果要用LoadGraph就换成:.setHint("javax.persistence.loadgraph", fetchGraph) .fetch(); return users; }
方式2:动态创建EntityGraph(适合临时场景)
如果只是某个查询需要临时指定加载的属性,不用在实体类上定义命名Graph,直接动态创建:
public List<User> getUsersWithRolesAndProfile() { JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager); QUser qUser = QUser.user; // 动态创建EntityGraph,指定要加载的属性 EntityGraph<User> dynamicLoadGraph = entityManager.createEntityGraph(User.class); dynamicLoadGraph.addAttributeNodes("roles", "profile"); // 同时加载roles和profile关联 // 应用LoadGraph List<User> users = queryFactory.selectFrom(qUser) .where(qUser.id.in(1L, 2L, 3L)) .setHint("javax.persistence.loadgraph", dynamicLoadGraph) .fetch(); return users; }
三、结合Spring Data JPA的简化用法
因为你用了Spring Data JPA 2.0.5,还可以直接在Repository层用@EntityGraph注解结合QueryDSL的查询,更简洁:
public interface UserRepository extends JpaRepository<User, Long>, QuerydslPredicateExecutor<User> { // 结合QueryDSL的Predicate查询,同时应用FetchGraph @Override @EntityGraph(value = "User.withRoles", type = EntityGraph.EntityGraphType.FETCH) List<User> findAll(Predicate predicate); // 也可以用LoadGraph @EntityGraph(value = "User.withRoles", type = EntityGraph.EntityGraphType.LOAD) List<User> findByUsernameContaining(String keyword); }
这里的type参数:FETCH对应JPA的FetchGraph,LOAD对应LoadGraph,调用这些方法时会自动应用对应的EntityGraph策略。
四、版本兼容性确认
你的环境完全没问题:
- Hibernate 5.2.14.Final完全支持JPA 2.1的EntityGraph规范
- QueryDSL 4.1.4的
JPAQuery支持通过setHint()设置JPA标准的hint参数 - Spring Data JPA 2.0.5也完美兼容QueryDSL和EntityGraph的结合
内容的提问来源于stack exchange,提问作者Leonel
相关产品推荐
相关产品推荐

