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); }
看完上面的代碼相比大家也能猜到,是的沒什么好方法,我將要返回的數(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)文章
SpringBoot webSocket實(shí)現(xiàn)發(fā)送廣播、點(diǎn)對(duì)點(diǎn)消息和Android接收
這篇文章主要介紹了SpringBoot webSocket實(shí)現(xiàn)發(fā)送廣播、點(diǎn)對(duì)點(diǎn)消息和Android接收,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-03-03java 中多線程生產(chǎn)者消費(fèi)者問(wèn)題詳細(xì)介紹
這篇文章主要介紹了java 中多線程生產(chǎn)者消費(fèi)者問(wèn)題詳細(xì)介紹的相關(guān)資料,希望通過(guò)本文能幫助到大家,需要的朋友可以參考下2017-09-09Java與Oracle實(shí)現(xiàn)事務(wù)(JDBC事務(wù))實(shí)例詳解
這篇文章主要介紹了Java與Oracle實(shí)現(xiàn)事務(wù)(JDBC事務(wù))實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-05-05springboot vue組件開發(fā)實(shí)現(xiàn)接口斷言功能
這篇文章主要為大家介紹了springboot+vue組件開發(fā)實(shí)現(xiàn)接口斷言功能,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05Eclipse創(chuàng)建java程序可執(zhí)行jar包教程
這篇文章主要為大家分享了Eclipse創(chuàng)建java程序可執(zhí)行jar包教程,具有一定的實(shí)用性和參考價(jià)值,感興趣的小伙伴們可以參考一下2016-05-05IDEA?下?Gradle?刪除多余無(wú)用依賴的處理方法
這篇文章主要介紹了IDEA下Gradle刪除多余無(wú)用依賴,使用該插件可以一定程度上幫助我們刪除無(wú)用依賴,但是也可能會(huì)多刪除有用的依賴,需要在使用插件自動(dòng)修復(fù)后手動(dòng)檢測(cè)項(xiàng)目,驗(yàn)證是否會(huì)出現(xiàn)問(wèn)題,避免導(dǎo)致上線發(fā)布錯(cuò)誤的負(fù)優(yōu)化2022-03-03java ThreadPool線程池的使用,線程池工具類用法說(shuō)明
這篇文章主要介紹了java ThreadPool線程池的使用,線程池工具類用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10