springboot jpa之返回表中部分字段的处理详解

 更新时间:2021年12月07日 10:01:06   作者:向阳居士  
这篇文章主要介绍了springboot jpa之返回表中部分字段的处理详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

springboot jpa返回表中部分字段

使用springboot jpa操作数据库可以加快我们的开发效率,对于简单的crud操作来说,使用jpa来开发不要太爽,但是说实话对于一些复杂的数据库操做jpa使用起来就不是这么爽了。

在开发中很多时候我们要返回的可能只是数据库表中或某个类中的一部分字段,这个要是用mybatis的话就很简单,直接在sql中select字段就好了,规范一点就数据传输类接一下,偷个懒的话直接用map接就完事了。但就是这么个小操作在jpa中就不能这么直接。

废话一大堆(⊙_⊙)下面是我在jpa中处理返回部分字段的方法。

/**
 * 房间已经预定的时间统计表
 */
public interface RoomOrderTimeRepository extends JpaRepository<RoomOrderTime,Integer>{ 
    @Query("select  new com.ddzrh.dto.RoomOrderTimeOutPut(r.orderTime,COUNT(r.orderTime) )" +
            " from RoomOrderTime as r " +
            " where r.roomTypeId =:roomId"+
            " GROUP BY r.orderTime" )
    List<RoomOrderTimeOutPut> queryRoomOrderTime(@Param("roomId") Integer roomId);  
}

看完上面的代码相比大家也能猜到,是的没什么好方法,我将要返回的数据都封装到了RoomOrderTimeOutPut类中。

@Data
public class RoomOrderTimeOutPut { 
    private Date orderTime;
    private Long orderNum; 
    public RoomOrderTimeOutPut(Date orderTime, Long orderNum) {
        this.orderTime = orderTime;
        this.orderNum = orderNum;
    }    
}

像上面的代码,我希望查询返回某个时间某间房的预定数,我就将希望返回的预定时间和预定数封装至RoomOrderTimeOutPut并写以这两个字段为入参的构造函数,这个构造函数一定要写。看Query中的sql 有一个new RoomOrderTimeOutPut 的操作,这里就调用了构造函数,根据构造函数的入参将数据库查出的值传入。

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注解,这种方式对于只需要返回表中部分的字段很方便,如果需要自定义返回字段名称,可以参考以下方法:

需求:统计注册人数

定义一个返回对象

使用@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]);
        });
    }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Spring Boot解决项目启动时初始化资源的方法

    Spring Boot解决项目启动时初始化资源的方法

    这篇文章主要给大家介绍了关于Spring Boot如何解决项目启动时初始化资源的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-05-05
  • Spring TaskScheduler使用实例解析

    Spring TaskScheduler使用实例解析

    这篇文章主要介绍了Spring TaskScheduler使用实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • 深入理解Struts2国际化信息机制

    深入理解Struts2国际化信息机制

    本篇文章主要介绍了深入理解Struts2国际化信息机制,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • SpringBoot2.x设置Session失效时间及失效跳转方式

    SpringBoot2.x设置Session失效时间及失效跳转方式

    这篇文章主要介绍了SpringBoot2.x设置Session失效时间及失效跳转方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • 使用Spring Cache设置缓存条件操作

    使用Spring Cache设置缓存条件操作

    这篇文章主要介绍了使用Spring Cache设置缓存条件操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • SpringBoot项目中配置application.yml中server.port不生效的问题

    SpringBoot项目中配置application.yml中server.port不生效的问题

    这篇文章主要介绍了SpringBoot项目中配置application.yml中server.port不生效的问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • 浅谈Maven安装及环境配置出错的解决办法

    浅谈Maven安装及环境配置出错的解决办法

    这篇文章主要介绍了浅谈Maven安装及环境配置出错的解决办法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • javaweb 项目初始配置的方法步骤

    javaweb 项目初始配置的方法步骤

    本文主要介绍了javaweb 项目初始配置的方法步骤,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • RabbitMQ进阶之消息可靠性详解

    RabbitMQ进阶之消息可靠性详解

    这篇文章主要介绍了RabbitMQ进阶之消息可靠性详解,abbitmq消息的投递过程中,怎么确保消息能不丢失,这是一个很重要的问题,哪怕我们做了Rabbitmq持久化,也不能保证我们的业务消息不会被丢失,需要的朋友可以参考下
    2023-08-08
  • Java高级特性基础之反射五连问

    Java高级特性基础之反射五连问

    反射赋予了我们在运行时分析类以及执行类中方法的能力。通过反射你可以获取任意一个类的所有属性和方法,你还可以调用这些方法和属性。本文就来和大家详细聊聊Java中的反射,感兴趣的可以了解一下
    2023-01-01

最新评论