springboot?jpa之返回表中部分字段的處理詳解
springboot jpa返回表中部分字段
使用springboot jpa操作數(shù)據(jù)庫(kù)可以加快我們的開發(fā)效率,對(duì)于簡(jiǎn)單的crud操作來(lái)說(shuō),使用jpa來(lái)開發(fā)不要太爽,但是說(shuō)實(shí)話對(duì)于一些復(fù)雜的數(shù)據(jù)庫(kù)操做jpa使用起來(lái)就不是這么爽了。
在開發(fā)中很多時(shí)候我們要返回的可能只是數(shù)據(jù)庫(kù)表中或某個(gè)類中的一部分字段,這個(gè)要是用mybatis的話就很簡(jiǎn)單,直接在sql中select字段就好了,規(guī)范一點(diǎn)就數(shù)據(jù)傳輸類接一下,偷個(gè)懶的話直接用map接就完事了。但就是這么個(gè)小操作在jpa中就不能這么直接。
廢話一大堆(⊙_⊙)下面是我在jpa中處理返回部分字段的方法。
/**
* 房間已經(jīng)預(yù)定的時(shí)間統(tǒng)計(jì)表
*/
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);
}
看完上面的代碼相比大家也能猜到,是的沒(méi)什么好方法,我將要返回的數(shù)據(jù)都封裝到了RoomOrderTimeOutPut類中。
@Data
public class RoomOrderTimeOutPut {
private Date orderTime;
private Long orderNum;
public RoomOrderTimeOutPut(Date orderTime, Long orderNum) {
this.orderTime = orderTime;
this.orderNum = orderNum;
}
}
像上面的代碼,我希望查詢返回某個(gè)時(shí)間某間房的預(yù)定數(shù),我就將希望返回的預(yù)定時(shí)間和預(yù)定數(shù)封裝至RoomOrderTimeOutPut并寫以這兩個(gè)字段為入?yún)⒌臉?gòu)造函數(shù),這個(gè)構(gòu)造函數(shù)一定要寫。看Query中的sql 有一個(gè)new RoomOrderTimeOutPut 的操作,這里就調(diào)用了構(gòu)造函數(shù),根據(jù)構(gòu)造函數(shù)的入?yún)?shù)據(jù)庫(kù)查出的值傳入。
jpa 自定義返回字段
實(shí)體類: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實(shí)體類中的一致,加上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);
}
測(cè)試:
@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中屬性名稱需要和實(shí)體類中字段名一致,且加上lombok包中的@Value注解,這種方式對(duì)于只需要返回表中部分的字段很方便,如果需要自定義返回字段名稱,可以參考以下方法:
需求:統(tǒng)計(jì)注冊(cè)人數(shù)
定義一個(gè)返回對(duì)象
使用@Query(value = "select new com.wd.cloud.uoserver.dto.TjVO(u.orgId ,count(u.orgId)) from User u group by orgId")進(jìn)行查詢。
@Value
public class TjVO {
Long orgId;
Long registerCount;
}
/**
* 按機(jī)構(gòu)統(tǒng)計(jì)注冊(cè)人數(shù)
* @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);
或者也可以用下面的方法:
定義一個(gè)接口,用getXxx定義返回字段。xxx需要和返回字段的別名一致。
如果不一致,可以使用org.springframework.beans.factory.annotation包中的@Value進(jìn)行映射
public interface TjDTO {
/**
* 所屬機(jī)構(gòu)
* @return
*/
Long getOrgId();
/**
* 注冊(cè)時(shí)間
* @return
*/
String getRegisterDate();
/**
* 注冊(cè)數(shù)量
* @return
*/
String getRegisterCount();
/**
* 管理員數(shù)量 當(dāng)別名與該getXXX名稱不一致時(shí),可以使用該注解調(diào)整
* @return
*/
@Value("#{target.adminCount}")
Long getManagerCount();
}
repository類:UserRepository.java添加方法tjByOrgId(),返回orgId和registerCount
/**
* 按天統(tǒng)計(jì)注冊(cè)人數(shù)
* @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();
/**
* 按機(jī)構(gòu)統(tǒng)計(jì)注冊(cè)人數(shù)
* @param pageable 分頁(yè)
* @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);
測(cè)試:
@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());
});
}
}
結(jié)果日志:
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
需求:根據(jù)機(jī)構(gòu)分組,統(tǒng)計(jì)機(jī)構(gòu)總?cè)藬?shù)和用戶類型為2的人數(shù)
@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();
}
}
測(cè)試:
@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={},總?cè)藬?shù)={},管理員人數(shù)={}", tjDTO[0], tjDTO[1], tjDTO[2]);
});
}
}

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java基于數(shù)據(jù)庫(kù)實(shí)現(xiàn)全局唯一ID的示例
本文主要介紹了java基于數(shù)據(jù)庫(kù)實(shí)現(xiàn)全局唯一ID的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04
springAOP完整實(shí)現(xiàn)過(guò)程
當(dāng)你調(diào)用SimpleService類的doSomething方法時(shí),上述的PerformanceAspect會(huì)自動(dòng)攔截此調(diào)用,并且記錄該方法的執(zhí)行時(shí)間,這樣你就完成了一個(gè)針對(duì)Spring的AOP入門級(jí)案例,感興趣的朋友一起看看吧2024-02-02
MyBatis-Plus 自定義sql語(yǔ)句的實(shí)現(xiàn)
這篇文章主要介紹了MyBatis-Plus 自定義sql語(yǔ)句的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
Java Clone深拷貝與淺拷貝的兩種實(shí)現(xiàn)方法
今天小編就為大家分享一篇關(guān)于Java Clone深拷貝與淺拷貝的兩種實(shí)現(xiàn)方法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-10-10
java解析JT808協(xié)議的實(shí)現(xiàn)代碼
這篇文章主要介紹了java解析JT808協(xié)議的實(shí)現(xiàn)代碼,需要的朋友可以參考下2020-03-03
SpringBoot整合Mybatis-plus實(shí)現(xiàn)多級(jí)評(píng)論功能
本文介紹了如何使用SpringBoot整合Mybatis-plus實(shí)現(xiàn)多級(jí)評(píng)論功能,同時(shí)提供了數(shù)據(jù)庫(kù)的設(shè)計(jì)和詳細(xì)的后端代碼,前端界面使用的Vue2,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-05-05
java中對(duì)list分頁(yè)并顯示數(shù)據(jù)到頁(yè)面實(shí)例代碼
這篇文章主要介紹了java中對(duì)list分頁(yè)并顯示數(shù)據(jù)到頁(yè)面實(shí)例代碼,分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-02-02

