Spring Boot 3中JPA Specification结合Projection未按需查询字段问题
Spring Boot 3.1.3 中 Specification 结合 Projection 实现按需字段查询
问题场景与代码
当前在Spring Boot 3.1.3中尝试结合Specification和Projection特性,但Hibernate生成的SQL会查询实体的所有字段,而非Projection指定的字段。相关代码如下:
Service层代码
public UserSimple bySpecification(Integer id) { Specification<UserInfo> spec = UserInfoSpecs.byId(id); UserSimple simpleList = repository.findBy(spec, q -> q.as(UserSimple.class).oneValue()); return simpleList; }
Projection(接口)
public interface UserSimple { String getName(); }
Specification代码
public interface UserInfoSpecs { static Specification<UserInfo> byId(Integer id) { return (root, query, builder) -> builder.equal(root.get("id"), id); } }
Entity实体类
@Entity @Getter @Setter public class UserInfo { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; private String name; private String email; }
Repository层代码
public interface UserInfoRepository extends JpaRepository<UserInfo, Integer>, JpaSpecificationExecutor<UserInfo> { Optional<UserInfo> findByName(String username); }
当前生成的SQL(查询所有字段):
org.hibernate.SQL: select u1_0.id,u1_0.email,u1_0.name,u1_0.password,u1_0.roles from user_info u1_0 where u1_0.id=? fetch first ? rows only
期望生成的SQL(仅查询指定字段):
org.hibernate.SQL: select u1_0.name from user_info u1_0 where u1_0.id=? fetch first ? rows only
解决方案
以下两种方式可实现按需查询指定字段:
方式一:在查询回调中指定选择字段(推荐)
修改Service层的查询逻辑,在findBy的回调中通过select方法明确指定Projection需要的字段,结合as(UserSimple.class)完成投影:
public UserSimple bySpecification(Integer id) { Specification<UserInfo> spec = UserInfoSpecs.byId(id); UserSimple simple = repository.findBy(spec, q -> q .select(root -> root.get("name")) .as(UserSimple.class) .oneValue()); return simple; }
方式二:在Specification中设置查询字段(耦合性高)
若希望Specification直接控制查询字段,可修改其实现,在构建查询时通过query.select()指定要查询的字段:
public interface UserInfoSpecs { static Specification<UserInfo> byId(Integer id) { return (root, query, builder) -> { query.select(root.get("name")); return builder.equal(root.get("id"), id); }; } }
说明:方式二会让Specification与具体Projection绑定,通用性不足,建议优先使用方式一。
内容的提问来源于stack exchange,提问作者Eduardo Gouveia
相关产品推荐
相关产品推荐

