Spring JPA自定義查詢結(jié)果的接收方式
一、標(biāo)準(zhǔn)使用方法
//構(gòu)建實(shí)體類
@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> {
}
//調(diào)用測(cè)試
@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());
}
}
如圖所示,插入成功。

二、自定義查詢結(jié)果的接收
假設(shè)我們不想查詢user表中的所有字段,而只需要其中的幾個(gè)字段作為前端輸出。
當(dāng)然,JPA給我們提供了自定義SQL的功能進(jìn)行個(gè)性化的查詢。使用@Query就可以自定義SQL語句,編寫自定義的查詢語句了。
但是,它的使用方式分為兩種:
- 一種是特定JPQL語言,這是通過實(shí)體對(duì)象來查詢屬性,而不用考慮對(duì)應(yīng)的表名稱和字段名稱。
- 一種是SQL語言,還是像原來一樣操作對(duì)應(yīng)的表和字段。
1.那么在UserRepository 中應(yīng)該怎么寫自定義查詢語句呢?
//創(chuàng)建個(gè)性化的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);
}
//調(diào)用
@RunWith(SpringRunner.class)
@SpringBootTest
class UserTest {
@Autowired
UserRepository userRepository;
@Test
void testUserDTO() {
UserDTO dto = userRepository.findUserDTOByID(1L);
assertEquals("zhangsan",dto.getUsername());
}
}
可能的錯(cuò)誤的查詢方式:
//1.意圖User實(shí)體自動(dòng)映射某些屬性到UserDTO
public interface UserRepository extends JpaRepository<User,Long> {
@Query("select u from User u where u.id =?1")
UserDTO findUserDTOByID(Long id);
//但是會(huì)報(bào)org.springframework.core.convert.ConverterNotFoundException錯(cuò)誤
}
//2.意圖挑出User的某些字段會(huì)自動(dòng)映射到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);
//但是會(huì)報(bào)org.springframework.core.convert.ConverterNotFoundException錯(cuò)誤
}
//3.意圖挑出User的某些字段會(huì)自動(dòng)映射到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);
//但是這會(huì)生成一個(gè)新表
}
在上面雖然UserDTO只是User中的子集,只有它的兩個(gè)屬性,但是如果直接用UserDTO接收查詢結(jié)構(gòu),就會(huì)報(bào)這種 類型轉(zhuǎn)換錯(cuò)誤。
這是因?yàn)閁serRepository是實(shí)體對(duì)象User的倉庫,必須用User來接收,不能用別的對(duì)象來接收。
那么我們能不能再創(chuàng)建一個(gè)UserDTORepository來接收查詢結(jié)果呢?
這是不行的,因?yàn)閁serDTORepository必須映射對(duì)應(yīng)的表,才能查詢UserDTO對(duì)象。而我們當(dāng)然不希望又創(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);
//倒是能接收到結(jié)果,但是丟失了屬性名稱,必須數(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);
//能接收到結(jié)果,但是UserDTO必須有構(gòu)造函數(shù),帶上所有參數(shù),也不方便
}
//3.定義接口來接收,使用的是projections接口投影機(jī)制
public interface IUser {
//定義這些getter方法才能接收結(jié)果
Long getId();
String getUsername();
}
//用接口接收查詢結(jié)果
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);
//能查詢到結(jié)果,但是必須用接口接收,可能不習(xí)慣
}
//4.泛型動(dòng)態(tài)查詢投影
public interface UserRepository extends JpaRepository<User,Long> {
<T> T findById(Long id, Class<T> type);
//只需要輸入ID和類類型就能查到結(jié)果,這個(gè)利用了方法名的查詢生成器機(jī)制,不用專門寫@Query
//同時(shí)使用動(dòng)態(tài)查詢投影,所以不用輸入很多參數(shù),方便了很多,強(qiáng)烈推薦
}
//5.用Map接收查詢的結(jié)果
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)點(diǎn)是不用構(gòu)造DTO直接輸出給前端
//缺點(diǎn)是查出來的不是對(duì)象,不方便再處理業(yè)務(wù)邏輯,若參數(shù)很多,就會(huì)很繁瑣
}
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring?Security自定義登錄頁面認(rèn)證過程常用配置
這篇文章主要為大家介紹了Spring?Security自定義登錄頁面認(rèn)證過程常用配置示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
java實(shí)現(xiàn)識(shí)別二維碼圖片功能
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)識(shí)別二維碼圖片功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04
java?web實(shí)現(xiàn)簡(jiǎn)單登錄注冊(cè)功能全過程(eclipse,mysql)
前期我們學(xué)習(xí)了javaweb項(xiàng)目用JDBC連接數(shù)據(jù)庫,還有數(shù)據(jù)庫的建表功能,下面這篇文章主要給大家介紹了關(guān)于java?web實(shí)現(xiàn)簡(jiǎn)單登錄注冊(cè)功能的相關(guān)資料,需要的朋友可以參考下2022-07-07
linux用java -jar啟動(dòng)jar包緩慢的問題
這篇文章主要介紹了linux用java -jar啟動(dòng)jar包緩慢的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,2023-09-09
Spring?Boot集成Milvus快速入門demo示例詳解
Milvus是一種高性能向量數(shù)據(jù)庫,支持從筆記本到大型分布式系統(tǒng)的多環(huán)境運(yùn)行,它以開源和云服務(wù)形式提供,是LFAI & Data Foundation的項(xiàng)目,采用Apache 2.0許可,Milvus特別支持高并行化和解耦的系統(tǒng)架構(gòu),使其能夠隨數(shù)據(jù)增長而擴(kuò)展,支持各種復(fù)雜搜索功能,滿足企業(yè)級(jí)AI應(yīng)用需求2024-09-09
通過實(shí)例深入學(xué)習(xí)Java的Struts框架中的OGNL表達(dá)式使用
這篇文章主要通過實(shí)例介紹了Java的Strus框架中的OGNL表達(dá)式使用,Struts框架是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下2015-11-11
java?集合工具類Collections及Comparable和Comparator排序詳解
這篇文章主要介紹了java集合工具類Collections及Comparable和Comparator排序詳解,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-06-06

