JPA 自定义返回字段

向右看齐 2022-04-24 02:30 416阅读 0赞

实体类:User.java

  1. @Data
  2. @Accessors(chain = true)
  3. @EqualsAndHashCode(callSuper = true)
  4. @Entity
  5. @Table(name = "user")
  6. public class User extends AbstractEntity {
  7. @Column(unique = true)
  8. private String username;
  9. private String password;
  10. private String nickname;
  11. private String email;
  12. @Column(name = "org_id")
  13. private Long orgId;
  14. @Column(name = "org_name")
  15. private String orgName;
  16. }

DTO类:UserDTO.java

  1. import lombok.Value;
  2. /**
  3. * @author wu qilong
  4. * @date 2019/4/11
  5. * @Description: 自定义返回值,字段名称要和User实体类中的一致,加上lombok.@Value注解。
  6. */
  7. @Value
  8. public class UserDTO {
  9. private String username;
  10. private String nickname;
  11. private String email;
  12. }

repository类:UserRepository.java

  1. /**
  2. * @author Wu Qilong
  3. * @date 2019/4/11
  4. * @Description:
  5. */
  6. public interface UserRepository extends JpaRepository<User, Long> {
  7. /**
  8. * 用户名查询
  9. *
  10. * @param username
  11. * @return
  12. */
  13. Optional<User> findByUsername(String username);
  14. /**
  15. * 用户名查询
  16. * @param username
  17. * @return
  18. */
  19. <T> Optional<T> findByUsername(String username, Class<T> type);
  20. }

测试:

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. public class UoServerApplicationTests {
  4. @Autowired
  5. UserRepository userRepository;
  6. @Test
  7. public void contextLoads() {
  8. UserDTO userDTO = userRepository.findByUsername("wuqilong", UserDTO.class).get();
  9. Console.log(userDTO);
  10. }
  11. }
  • 注意:返回的DTO中属性名称需要和实体类中字段名一致,且加上lombok包中的@Value注解,这种方式对于只需要返回表中部分的字段很方便,如果需要自定义返回字段名称,可以参考以下方法:
  • 需求:统计注册人数
  1. 定义一个返回对象
  2. 使用@Query(value = "select new com.wd.cloud.uoserver.dto.TjVO(u.orgId ,count(u.orgId)) from User u group by orgId")进行查询。

    @Value
    public class TjVO {

    1. Long orgId;
    2. Long registerCount;

    }

    /**

    1. * 按机构统计注册人数
    2. * @param pageable
    3. * @return
    4. */
    5. @Query(value = "select new com.wd.cloud.uoserver.dto.TjVO(u.orgId ,count(u.orgId)) from User u group by orgId")
    6. Page<TjVO> tjByOrgId(Pageable pageable);

或者也可以用下面的方法:

定义一个接口,用getXxx定义返回字段。xxx需要和返回字段的别名一致。
如果不一致,可以使用org.springframework.beans.factory.annotation包中的@Value进行映射

  1. public interface TjDTO {
  2. /**
  3. * 所属机构
  4. * @return
  5. */
  6. Long getOrgId();
  7. /**
  8. * 注册时间
  9. * @return
  10. */
  11. String getRegisterDate();
  12. /**
  13. * 注册数量
  14. * @return
  15. */
  16. String getRegisterCount();
  17. /**
  18. * 管理员数量 当别名与该getXXX名称不一致时,可以使用该注解调整
  19. * @return
  20. */
  21. @Value("#{target.adminCount}")
  22. Long getManagerCount();
  23. }

repository类:UserRepository.java添加方法tjByOrgId(),返回orgId和registerCount

  1. /**
  2. * 按天统计注册人数
  3. * @return
  4. */
  5. @Query(value = "select DATE_FORMAT(gmt_create,\"%Y-%m-%d\") as registerDate,count(*) as registerCount from user group by registerDate",nativeQuery = true)
  6. List<TjDTO> tj();
  7. /**
  8. * 按机构统计注册人数
  9. * @param pageable 分页
  10. * @return
  11. */
  12. @Query(value = "select org_id as orgId,count(*) as registerCount from user group by orgId",
  13. countQuery = "select count(*) from user group by org_id", nativeQuery = true)
  14. Page<TjDTO> tjByOrgId(Pageable pageable);

测试:

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. public class UoServerApplicationTests {
  4. @Autowired
  5. UserRepository userRepository;
  6. @Test
  7. public void contextLoads() {
  8. List<TjDTO> tjDTOList = userRepository.tj();
  9. tjDTOList.forEach(tjDTO -> {
  10. Console.log("registerDate={},registerCount={}", tjDTO.getRegisterDate(), tjDTO.getRegisterCount());
  11. });
  12. }
  13. }

结果日志:

  1. Hibernate: select DATE_FORMAT(gmt_create,"%Y-%m-%d") as registerDate,count(*) >as registerCount from user group by registerDate
  2. registerDate=2019-01-28,registerCount=7393
  3. registerDate=2019-03-07,registerCount=1
  • 需求:根据机构分组,统计机构总人数和用户类型为2的人数

    @Component
    public class SpecBuilder {

    1. @PersistenceContext
    2. private EntityManager entityManager;
    3. public List<Object[]> tj(Long orgId) {
    4. CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    5. CriteriaQuery<Object[]> query = cb.createQuery(Object[].class);
    6. Root<User> root = query.from(User.class);
    7. //拼接where条件
    8. List<Predicate> predicateList = new ArrayList<Predicate>();
    9. if (orgId != null) {
    10. predicateList.add(cb.equal(root.get("orgId"), orgId));
    11. }
    12. //加上where条件
    13. query.where(ArrayUtil.toArray(predicateList, Predicate.class));
    14. query.multiselect(root.get("orgId"),
    15. cb.count(root),
    16. cb.sum(cb.<Integer>selectCase().when(cb.equal(root.get("userType"), 2), 1).otherwise(0)));
    17. query.groupBy(root.get("orgId"));
    18. //最终sql: select org_id,count(id),sum(case when user_type=2 then 1 else 0 end) from user where org_id=?1 group by org_id;
    19. TypedQuery<Object[]> typedQuery = entityManager.createQuery(query);
    20. return typedQuery.getResultList();
    21. }

    }

测试:

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. public class UoServerApplicationTests {
  4. @Autowired
  5. SpecBuilder specBuilder;
  6. @Test
  7. public void contextLoads() {
  8. List<Object[]> tjDTOList1 = specBuilder.tj(169L);
  9. tjDTOList1.forEach(tjDTO -> {
  10. Console.log("orgId={},总人数={},管理员人数={}", tjDTO[0], tjDTO[1], tjDTO[2]);
  11. });
  12. }
  13. }

format_png

感谢https://www.hutool.cn/ 作者提供hutool工具包

参考:https://docs.spring.io/spring-data/jpa/docs/2.1.5.RELEASE/reference/html/#projections

https://www.jianshu.com/p/fbd157c3b4a4

发表评论

表情:
评论列表 (有 0 条评论,416人围观)

还没有评论,来说两句吧...

相关阅读

    相关 JPA定义查询

    在使用JPA过程中,写nativeQuery无法满足所有需求,只能寻求其他的途径,下面是一种方法 / 增加过滤条件 @return