Spring JPA自定義查詢結果的接收方式
一、標準使用方法
//構建實體類 @Getter @Setter @Entity @Builder @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor(access = AccessLevel.PRIVATE) @Table(name = "user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private Integer age; private String address; } //繼承JPA public interface UserRepository extends JpaRepository<User,Long> { } //調用測試 @RunWith(SpringRunner.class) @SpringBootTest class UserTest { @Autowired UserRepository userRepository; @Test void testUser() { User newUser = User.builder() .id(1L) .username("zhangsan") .age(18) .address("北京市").build(); User savedUser = userRepository.save(newUser); assertEquals("zhangsan",savedUser.getUsername()); } }
如圖所示,插入成功。
二、自定義查詢結果的接收
假設我們不想查詢user表中的所有字段,而只需要其中的幾個字段作為前端輸出。
當然,JPA給我們提供了自定義SQL的功能進行個性化的查詢。使用@Query就可以自定義SQL語句,編寫自定義的查詢語句了。
但是,它的使用方式分為兩種:
- 一種是特定JPQL語言,這是通過實體對象來查詢屬性,而不用考慮對應的表名稱和字段名稱。
- 一種是SQL語言,還是像原來一樣操作對應的表和字段。
1.那么在UserRepository 中應該怎么寫自定義查詢語句呢?
//創(chuàng)建個性化的DTO用于接收 @Value public class UserDTO { Long id; String username; } //寫sql語句 public interface UserRepository extends JpaRepository<User,Long> { //@Query("select u from User u where u.id =?1") //是像這樣,還是怎么寫呢? UserDTO findUserDTOByID(Long id); } //調用 @RunWith(SpringRunner.class) @SpringBootTest class UserTest { @Autowired UserRepository userRepository; @Test void testUserDTO() { UserDTO dto = userRepository.findUserDTOByID(1L); assertEquals("zhangsan",dto.getUsername()); } }
可能的錯誤的查詢方式:
//1.意圖User實體自動映射某些屬性到UserDTO public interface UserRepository extends JpaRepository<User,Long> { @Query("select u from User u where u.id =?1") UserDTO findUserDTOByID(Long id); //但是會報org.springframework.core.convert.ConverterNotFoundException錯誤 } //2.意圖挑出User的某些字段會自動映射到UserDTO public interface UserRepository extends JpaRepository<User,Long> { @Query("select u.id,u.username from User u where u.id =?1") UserDTO findUserDTOByID(Long id); //但是會報org.springframework.core.convert.ConverterNotFoundException錯誤 } //3.意圖挑出User的某些字段會自動映射到UserDTO public interface UserDTORepository extends JpaRepository<UserDTO,Long> { @Query("select u.id,u.username from User u where u.id =?1") UserDTO findByID(Long id); //但是這會生成一個新表 }
在上面雖然UserDTO只是User中的子集,只有它的兩個屬性,但是如果直接用UserDTO接收查詢結構,就會報這種 類型轉換錯誤。
這是因為UserRepository是實體對象User的倉庫,必須用User來接收,不能用別的對象來接收。
那么我們能不能再創(chuàng)建一個UserDTORepository來接收查詢結果呢?
這是不行的,因為UserDTORepository必須映射對應的表,才能查詢UserDTO對象。而我們當然不希望又創(chuàng)建與User相似的表。
正確的查詢方式:
//1.使用Object接收 public interface UserRepository extends JpaRepository<User,Long> { @Query("select u.id,u.username from User u where u.id =?1") Object findUserDTOByID(Long id); //倒是能接收到結果,但是丟失了屬性名稱,必須數(shù)組的索引訪問,不方便 } //2.使用全限定名接收 public interface UserRepository extends JpaRepository<User,Long> { @Query("select new com.example.admin.ums.domain.user.UserDTO(id,username) from User u where u.id =?1") UserDTO findUserDTOByID(Long id); //能接收到結果,但是UserDTO必須有構造函數(shù),帶上所有參數(shù),也不方便 } //3.定義接口來接收,使用的是projections接口投影機制 public interface IUser { //定義這些getter方法才能接收結果 Long getId(); String getUsername(); } //用接口接收查詢結果 public interface UserRepository extends JpaRepository<User,Long> { @Query("select u.id as id ,u.username as username from User u where u.id =?1") IUser findUserDTOByID(Long id); //能查詢到結果,但是必須用接口接收,可能不習慣 } //4.泛型動態(tài)查詢投影 public interface UserRepository extends JpaRepository<User,Long> { <T> T findById(Long id, Class<T> type); //只需要輸入ID和類類型就能查到結果,這個利用了方法名的查詢生成器機制,不用專門寫@Query //同時使用動態(tài)查詢投影,所以不用輸入很多參數(shù),方便了很多,強烈推薦 } //5.用Map接收查詢的結果 public interface UserRepository extends JpaRepository<User,Long> { @Query("select u.id as id ,u.username as username, u.address as address from User u where u.id =?1") Map<String,Object> findUserDTO(Long id); //需要寫JPQL語句,必須用as取別名,否則就沒有key值 //優(yōu)點是不用構造DTO直接輸出給前端 //缺點是查出來的不是對象,不方便再處理業(yè)務邏輯,若參數(shù)很多,就會很繁瑣 }
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Spring?Security自定義登錄頁面認證過程常用配置
這篇文章主要為大家介紹了Spring?Security自定義登錄頁面認證過程常用配置示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08java?web實現(xiàn)簡單登錄注冊功能全過程(eclipse,mysql)
前期我們學習了javaweb項目用JDBC連接數(shù)據(jù)庫,還有數(shù)據(jù)庫的建表功能,下面這篇文章主要給大家介紹了關于java?web實現(xiàn)簡單登錄注冊功能的相關資料,需要的朋友可以參考下2022-07-07Spring?Boot集成Milvus快速入門demo示例詳解
Milvus是一種高性能向量數(shù)據(jù)庫,支持從筆記本到大型分布式系統(tǒng)的多環(huán)境運行,它以開源和云服務形式提供,是LFAI & Data Foundation的項目,采用Apache 2.0許可,Milvus特別支持高并行化和解耦的系統(tǒng)架構,使其能夠隨數(shù)據(jù)增長而擴展,支持各種復雜搜索功能,滿足企業(yè)級AI應用需求2024-09-09通過實例深入學習Java的Struts框架中的OGNL表達式使用
這篇文章主要通過實例介紹了Java的Strus框架中的OGNL表達式使用,Struts框架是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下2015-11-11java?集合工具類Collections及Comparable和Comparator排序詳解
這篇文章主要介紹了java集合工具類Collections及Comparable和Comparator排序詳解,文章圍繞主題展開詳細的內容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-06-06