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;
@Value
public class UserDTO {
private String username;
private String nickname;
private String email;
}
repository类:UserRepository.java
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
<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;
}
@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 {
Long getOrgId();
String getRegisterDate();
String getRegisterCount();
@Value("#{target.adminCount}")
Long getManagerCount();
}
repository类:UserRepository.java添加方法tjByOrgId(),返回orgId和registerCount
@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();
@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]);
});
}
}
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341