一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 詳解spring-data-jpa中jpql的投影查詢

詳解spring-data-jpa中jpql的投影查詢

2022-01-24 01:05KevinBlandy Java教程

投影查詢,就是僅僅檢索表的部分字段。而不是粗暴的 SELECT * FROM...檢索出所有列數據,這篇文章主要介紹了spring-data-jpa中jpql的投影查詢,需要的朋友可以參考下

投影查詢,就是僅僅檢索表的部分字段。而不是粗暴的 SELECT * FROM...檢索出所有列數據。例如檢索用戶余額信息的時候,就不需要檢索用戶的頭像,創建日期等字段。節省了帶寬傳輸和內存占用,也避免了可能暴露更多數據給客戶端。

這里先啰嗦一下jpql的一些注意點

  • 操作的是對象 @Entity, 不是表, 操作的是對象屬性, 也不是表字段
  • 默認Entity名稱就是類名稱大寫, 也可以通過修改 @Entity 屬性的注解來修改
  • 不支持使用 `` 符號, 不支持在末尾添加分號: ;
  • 支持使用 AS 關鍵字起別名

準備一個演示用的實體類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import javax.persistence.*;
 
import java.io.Serializable;
import java.time.LocalDateTime;
 
/**
 * 用戶
 */
@Entity
@Table(name = "user", indexes = {
        @Index(columnList = "account", unique = true),
})
@org.hibernate.annotations.Table(appliesTo = "user", comment = "用戶")
public class User implements Serializable {
 
    /**
     *
     */
    private static final long serialVersionUID = -129586628554861093L;
 
    @Id
    @Column(columnDefinition = "INT(11) UNSIGNED COMMENT 'id'")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
 
    // 登錄賬戶
    @Column(columnDefinition = "VARCHAR(20) COMMENT '登錄賬戶'", nullable = false)
    private String account;
    
    // 昵稱
    @Column(columnDefinition = "VARCHAR(20) COMMENT '昵稱'")
    private String name;
 
    // 頭像
    @Column(columnDefinition = "VARCHAR(255) COMMENT '頭像'")
    private String avatar;
 
    // 創建時間
    @Column(name = "created_date", columnDefinition = "timestamp DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間'", nullable = false)
    private LocalDateTime createdDate;
 
    // 最后修改時間
    @Column(name = "last_modified_date", columnDefinition = "timestamp NULL DEFAULT NULL COMMENT '最后一次修改時間'")
    private LocalDateTime lastModifiedDate;
 
    // 記錄狀態
    @Column(columnDefinition = "TINYINT(1) unsigned COMMENT '是否啟用'", nullable = false)
    private Boolean enabled;
}

檢索單行單列數據

單行單列數據,比較簡單了。返回的列數據類型是什么,Repository接口中檢索方法的返回值就定義什么即可。

根據用戶ID檢索 賬戶字段

?
1
2
3
4
5
6
7
8
9
10
public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecificationExecutor <User> {
    
    /**
     * 根據用戶ID,檢索賬戶信息
     * @param id
     * @return
     */
    @Query("SELECT u.account FROM User AS u WHERE u.id = :id")
    String accountById(@Param("id") Integer id);
}

測試代碼

?
1
2
3
4
5
6
7
8
9
@Autowired
private UserRepository userRepository;
 
@Test
@Transactional(readOnly = true)
public void test () {
    String account = userRepository.accountById(1);
    LOGGER.info("account={}", account);
}

執行日志

在日志中可以看到執行的SQL符合要求,僅僅檢索了一個列,并且返回了正確的結果。

?
1
2
3
4
5
6
7
8
9
Hibernate:
    select
        user0_.account as col_0_0_
    from
        user user0_
    where
        user0_.id=?
 o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [INTEGER] - [1]
 i.s.jpa.test.JpaApplicationTest          : account=KevinBlandy

檢索單行多列數據

使用自定義對象 的構造器封裝結果集

自定義一個封裝結果集的對象

這里直接繼承了User類,并且需要通過構造函數來定義需要投影檢索的列

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.time.LocalDateTime;
 
public class UserDTO extends User {
 
    /**
     *
     */
    private static final long serialVersionUID = 6393508321723484097L;
    
    public UserDTO(String account, String name, LocalDateTime createdDate) {
        super.setAccount(account);
        super.setName(name);
        super.setCreatedDate(createdDate);
    }
}

根據檢索出用戶的基本信息:賬戶,昵稱,創建時間,封裝結果集為UserDTO對象

使用jpql中的NEW關鍵字指定自定義對象的全路徑,并且在構造函數中指定要檢索的列,既有sql的語法,又有面向對象的思想。

?
1
2
3
4
5
6
7
/**
 * 根據檢索出用戶的基本信息:賬戶,昵稱,創建時間,封裝結果集為UserDTO對象
 * @param id
 * @return
 */
@Query("SELECT NEW io.springboot.jpa.entity.UserDTO(u.account, u.name, u.createdDate) FROM User AS u WHERE u.id = :id")
UserDTO querySimpleInfoById(@Param("id") Integer id);

測試

?
1
2
3
4
5
6
7
8
9
@Autowired
private UserRepository userRepository;
 
@Test
@Transactional(readOnly = true)
public void test () {
    UserDTO userDTO = userRepository.querySimpleInfoById(1);
    LOGGER.info("user={}", userDTO);
}

執行日志

?
1
2
3
4
5
6
7
8
9
10
11
Hibernate:
    select
        user0_.account as col_0_0_,
        user0_.name as col_1_0_,
        user0_.created_date as col_2_0_
    from
        user user0_
    where
        user0_.id=?
o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [INTEGER] - [1]
i.s.jpa.test.JpaApplicationTest          : user=User [id=null, account=KevinBlandy, name=Vin, avatar=null, createdDate=2020-07-16T10:39:02, lastModifiedDate=null, enabled=null]

使用 Oject[] 封裝結果集

把結果集封裝為數組集合,并不需要重新定義對象,但是缺點就是需要自己記住每個數組下標下的數據代表的是什么 。

根據檢索出用戶的基本信息:賬戶,昵稱,創建時間,封裝結果集為Object數組

?
1
2
3
4
5
6
7
/**
 * 根據檢索出用戶的基本信息:賬戶,昵稱,創建時間,封裝結果集為“Object[]”
 * @param id
 * @return
 */
@Query("SELECT u.account, u.name, u.createdDate FROM User AS u WHERE u.id = :id")
Object querySimpleInfoById(@Param("id") Integer id);

注意,這里的返回值定義的是Object,而不是想象中的Object[],返回值定義為Object[],jpa就會把結果集封裝為一個二維數組,適合多行多列的情況。

這里演示的是根據id檢索,只可能是單行,多列。所以定義成Object,自己強轉換一下就好了。

測試

?
1
2
3
4
5
6
7
8
9
10
11
12
@Autowired
private UserRepository userRepository;
 
@Test
@Transactional(readOnly = true)
public void test () {
    // 強制轉換為Object[]
    Object[] results = (Object[]) userRepository.querySimpleInfoById(1);
    for (Object result : results) {
        LOGGER.info("result={}", result);   // 遍歷數組的所偶結果
    }
}

執行日志

?
1
2
3
4
5
6
7
8
9
10
11
12
13
Hibernate:
    select
        user0_.account as col_0_0_,
        user0_.name as col_1_0_,
        user0_.created_date as col_2_0_
    from
        user user0_
    where
        user0_.id=?
o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [INTEGER] - [1]
i.s.jpa.test.JpaApplicationTest          : result=KevinBlandy
i.s.jpa.test.JpaApplicationTest          : result=Vin
i.s.jpa.test.JpaApplicationTest          : result=2020-07-16T10:39:02

使用 Map<String, Object> 封裝結果集

使用map作為結果集的好處就是,不需要重新定義對象。而且可以根據key找到自己要的字段。我覺得最方便的一種 方法了,借助于spring的,BeanUtils,可以把Map轉換為對象。

根據檢索出用戶的基本信息:賬戶,昵稱,創建時間,封裝結果集為“Map<String, Object>”

?
1
2
3
4
5
6
7
/**
 * 根據檢索出用戶的基本信息:賬戶,昵稱,創建時間,封裝結果集為“Map<String, Object>”
 * @param id
 * @return
 */
@Query("SELECT NEW MAP(u.account AS account, u.name AS name, u.createdDate AS createdDate) FROM User AS u WHERE u.id = :id")
Map<String, Object> querySimpleInfoById(@Param("id") Integer id);

需要對檢索的列, 使用AS起別名, 作為key的名稱,如果不使用AS別名的話,單行單列的情況下, key = null, 多行的情況下, key = 序號(從0開始)

?
1
2
3
4
{
    "0":"Vin",
    "1":“KevinBlandy”
}

測試代碼

?
1
2
3
4
5
6
7
8
9
@Autowired
private UserRepository userRepository;
 
@Test
@Transactional(readOnly = true)
public void test () {
    Map<String, Object> result = userRepository.querySimpleInfoById(1);
    LOGGER.info("result={}", result);  
}

執行日志

?
1
2
3
4
5
6
7
8
9
10
11
Hibernate:
    select
        user0_.account as col_0_0_,
        user0_.name as col_1_0_,
        user0_.created_date as col_2_0_
    from
        user user0_
    where
        user0_.id=?
o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [INTEGER] - [1]
i.s.jpa.test.JpaApplicationTest          : result={name=Vin, account=KevinBlandy, createdDate=2020-07-16T10:39:02}

檢索多列N行

對于有多行的記錄封裝,就很簡單了。在上面的基礎上,把返回值結果修改為數組或者Collection子類即可。

  • 單行多列 List<String>
  • 多行多列 List<Map<String, Object>>
  • 多行隊列 List<Object[]>
  • 多行隊列 List<UseDTO>
  • 多行隊列 Object[],每一個Object元素都是一個數組
  • ...

原文:https://springboot.io/t/topic/2234

到此這篇關于spring-data-jpa中jpql的投影查詢的文章就介紹到這了,更多相關spring-data-jpa jpql投影查詢內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://www.cnblogs.com/kevinblandy/p/13321865.html

延伸 · 閱讀

精彩推薦
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7482021-02-04
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
主站蜘蛛池模板: 天美传媒果冻传媒星空传媒 | 动漫美女强行被吸乳做羞羞事 | eee在线播放成人免费 | 午夜性爽视频男人的天堂在线 | 男女发生性关系视频 | 精品无码人妻一区二区免费AV | 天天乐影院 | 艾秋麻豆果冻剧传媒在线播放 | 免费观看二十女人一摸是水 | 久久精品亚洲牛牛影视 | 国产色综合久久五月色婷婷中文 | 色人阁导航 | 天堂a视频 | 青青青青青国产免费手机看视频 | 久久久久久久99精品免费观看 | 国产亚洲一欧美一区二区三区 | 亚洲天堂精品在线观看 | 欧美亚洲国产精品久久久 | 九九热在线视频观看这里只有精品 | 91精品大神国产在线播放 | 精品久久久久香蕉网 | brazzers欧美教师| 四虎影院在线免费观看 | 亚洲区一 | 日韩在线 在线播放 | 91精品大神国产在线播放 | 国内剧情麻豆 | 国产精品热久久毛片 | 91麻豆精东果冻天美传媒老狼 | 亚洲男人第一天堂 | 美女脱一净二净不带胸罩 | 久久伊人中文字幕有码 | 亚洲邪恶天堂影院在线观看 | 91porny紧身翘臀 | 国产精品资源站 | 免费超级乱淫视频播放性 | 日韩高清无砖砖区2022 | 日本色播 | 四虎免费影院4hu永久免费 | www91在线观看 | 男人使劲躁女人视频免费 |