JPA 自定义返回字段

 实体类:User.java

@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@Entity
@Table(name = "user")
public class User extends AbstractEntity {

    @Column(unique = true)
    private String username;

    private String password;

    private String nickname;

    private String email;

    @Column(name = "org_id")
    private Long orgId;

    @Column(name = "org_name")
    private String orgName;
}

DTO类:UserDTO.java

import lombok.Value;

/**
 * @author wu qilong
 * @date 2019/4/11
 * @Description: 自定义返回值,字段名称要和User实体类中的一致,加上lombok.@Value注解。
 */
@Value
public class UserDTO {

    private String username;

    private String nickname;

    private String email;
}

repository类:UserRepository.java

/**
 * @author Wu Qilong
 * @date 2019/4/11
 * @Description:
 */
public interface UserRepository extends JpaRepository<User, Long> {

    /**
     * 用户名查询
     *
     * @param username
     * @return
     */
    Optional<User> findByUsername(String username);


    /**
     * 用户名查询
     * @param username
     * @return
     */
    <T> Optional<T> findByUsername(String username, Class<T> type);
}

  测试:

@RunWith(SpringRunner.class)
@SpringBootTest
public class UoServerApplicationTests {

    @Autowired
    UserRepository userRepository;

    @Test
    public void contextLoads() {
        UserDTO userDTO = userRepository.findByUsername("wuqilong", UserDTO.class).get();
        Console.log(userDTO);
    }
}
  • 注意:返回的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 {

    Long orgId;

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

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

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

public interface TjDTO {

    /**
     * 所属机构
     * @return
     */
    Long getOrgId();
    /**
     * 注册时间
     * @return
     */
    String getRegisterDate();

    /**
     * 注册数量
     * @return
     */
    String getRegisterCount();

    /**
     * 管理员数量 当别名与该getXXX名称不一致时,可以使用该注解调整
     * @return
     */
    @Value("#{target.adminCount}")
    Long getManagerCount();

}

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

 /**
     * 按天统计注册人数
     * @return
     */
    @Query(value = "select DATE_FORMAT(gmt_create,\"%Y-%m-%d\") as registerDate,count(*) as registerCount from user group by registerDate",nativeQuery = true)
    List<TjDTO> tj();

    /**
     * 按机构统计注册人数
     * @param pageable  分页
     * @return
     */
    @Query(value = "select org_id as orgId,count(*) as registerCount from user group by orgId",
            countQuery = "select count(*) from user group by org_id", nativeQuery = true)
    Page<TjDTO> tjByOrgId(Pageable pageable);

测试:

@RunWith(SpringRunner.class)
@SpringBootTest
public class UoServerApplicationTests {

    @Autowired
    UserRepository userRepository;

    @Test
    public void contextLoads() {
        List<TjDTO> tjDTOList = userRepository.tj();
        tjDTOList.forEach(tjDTO -> {
            Console.log("registerDate={},registerCount={}", tjDTO.getRegisterDate(), tjDTO.getRegisterCount());
        });
    }
}

结果日志:

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

    @PersistenceContext
    private EntityManager entityManager;

    public List<Object[]> tj(Long orgId) {
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        CriteriaQuery<Object[]> query = cb.createQuery(Object[].class);
        Root<User> root = query.from(User.class);
        //拼接where条件
        List<Predicate> predicateList = new ArrayList<Predicate>();
        if (orgId != null) {
            predicateList.add(cb.equal(root.get("orgId"), orgId));
        }
        //加上where条件
        query.where(ArrayUtil.toArray(predicateList, Predicate.class));
        query.multiselect(root.get("orgId"),
                cb.count(root),
                cb.sum(cb.<Integer>selectCase().when(cb.equal(root.get("userType"), 2), 1).otherwise(0)));
        query.groupBy(root.get("orgId"));
        //最终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;
        TypedQuery<Object[]> typedQuery = entityManager.createQuery(query);
        return typedQuery.getResultList();
    }

}

测试:

@RunWith(SpringRunner.class)
@SpringBootTest
public class UoServerApplicationTests {

    @Autowired
    SpecBuilder specBuilder;

    @Test
    public void contextLoads() {
        List<Object[]> tjDTOList1 = specBuilder.tj(169L);
        tjDTOList1.forEach(tjDTO -> {
            Console.log("orgId={},总人数={},管理员人数={}", tjDTO[0], tjDTO[1], tjDTO[2]);
        });
    }
}

 

感谢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
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
JPA 中,可以使用以下方法来指定返回字段: 1. 使用 @Query 注解:可以在自定义的查询方法上使用 @Query 注解,通过编写 JPQL 或者原生 SQL 查询语句来指定返回字段。在查询语句中,可以使用 SELECT 关键字来选择需要返回字段,例如: ```java @Repository public interface UserRepository extends JpaRepository<User, Long> { @Query("SELECT u.name, u.age FROM User u") List<Object[]> findUserNameAndAge(); } ``` 上述代码中,使用 @Query 注解指定了一个自定义查询方法,查询返回的是一个 Object 数组,包含了 name 和 age 两个字段。 2. 使用 Projections:JPA 还提供了 Projections 的功能,可以通过接口的方式来定义需要返回字段。首先定义一个接口,接口中声明需要返回字段名和对应的 getter 方法: ```java public interface UserNameAndAge { String getName(); Integer getAge(); } ``` 然后在 Repository 中使用 Projections 的方式来指定返回字段: ```java @Repository public interface UserRepository extends JpaRepository<User, Long> { List<UserNameAndAge> findByName(String name); } ``` 上述代码中,定义了一个 UserNameAndAge 接口,包含了 getName() 和 getAge() 方法。在 UserRepository 中使用该接口作为返回类型,JPA 会自动根据接口方法名来生成查询语句,并返回符合接口定义的字段。 这些是两种常用的方式来指定返回字段,你可以根据具体的需求选择适合的方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值