如何让Spring Data JDBC不自动获取关联的Privileges集合
如何让Spring Data JDBC不自动加载关联的集合字段
你定义了如下Users实体:
public class Users { private final @Id @With long id; private final String userName; private final String firstName; private final String lastName; private final LocalDateTime created; @With @MappedCollection(idColumn = "users_id") private final Set<Privileges> privileges; }
并编写了查询方法:
@Query("select u.id, u.userName, u.firstName, u.lastName from users u order by u.username") List<Users> findsAllOrderedByUserName();
执行时Spring Data JDBC会为每个用户额外查询privileges集合,产生大量N+1查询,想要避免这种自动加载行为,有以下几种可行方案:
方案1:使用DTO/投影返回所需字段
这是最直接高效的方式,创建一个仅包含你需要字段的DTO(推荐用Java Record简化代码),让查询方法返回该类型,Spring Data JDBC不会尝试加载实体的关联集合。
示例代码:
// 定义投影类 public record UserSummary(long id, String userName, String firstName, String lastName) {} // 修改仓库查询方法 @Query("select u.id, u.userName, u.firstName, u.lastName from users u order by u.userName") List<UserSummary> findsAllOrderedByUserName();
方案2:为关联集合开启延迟加载
如果必须返回Users实体,可以通过延迟加载让集合仅在主动调用时才被加载。需要注意几个前提:
- 集合字段不能是
final(Spring需要生成代理类包装集合) - 添加
@LazyCollection注解(Spring Data JDBC 2.0及以上版本支持)
修改实体代码:
public class Users { private final @Id @With long id; private final String userName; private final String firstName; private final String lastName; private final LocalDateTime created; @With @MappedCollection(idColumn = "users_id") @LazyCollection(LazyCollectionOption.TRUE) // 开启延迟加载 private Set<Privileges> privileges; // 去掉final修饰符 }
修改后,默认查询用户时不会加载privileges,只有当你调用user.getPrivileges()时才会触发对应的查询。
方案3:返回非实体类型
如果业务场景不需要完整的Users实体,也可以直接返回Map<String, Object>或者元组类型,同样不会触发关联集合的加载:
@Query("select u.id, u.userName, u.firstName, u.lastName from users u order by u.userName") List<Map<String, Object>> findsAllOrderedByUserName();
内容的提问来源于stack exchange,提问作者Thomas Lang
相关产品推荐
相关产品推荐

