中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何理解Spring?Data?JPA查詢方式及方法名查詢規則

發布時間:2021-11-25 13:14:01 來源:億速云 閱讀:199 作者:柒染 欄目:開發技術

這篇文章給大家介紹如何理解Spring Data JPA查詢方式及方法名查詢規則,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

Spring Data JPA查詢方式及方法名查詢規則

Spring Data JPA

一、通過解析方法名創建查詢

在執行查詢時,Spring Data JPA框架會把方法名進行解析,解析到前綴比如 get、getBy、find、findBy、read、readBy時,會先把這些前綴截取掉,然后對剩下部分進行解析,剩下部分分為兩種:一是只有屬性名,二是屬性名+條件;條件很好解析,解析的關鍵在于屬性名,下面拿一個具體的例子來幫助大家更好的理解屬性名解析規則。

解析規則例子:比如實體為Product,方法為findByGoodsTypeDetail ();

1、首先截取掉 findBy,然后對剩下的屬性進行解析;

2、先判斷 goodsTypeDetail(根據 POJO 規范,首字母變為小寫,下同)是否為 Product的一個屬性,如果是,則表示根據該屬性進行查詢;如果沒有該屬性,繼續第三步;

3、從右往左截取第一個大寫字母開頭的字符串(本方法為 Detail),然后對比剩下的字符串(本方法為goodsType)是否為 Product的一個屬性,如果是,則表示根據該屬性進行查詢;如果沒有該屬性,則重復第三步,繼續從右往左截取(此處為TypeDetail,剩下goods),就這樣一直循環到最終;假設 goods為 Product的一個屬性,則說明goods不是常量類型,而是一個對象類型;

4、此時剩下字符串 TypeDetail,先判斷goods對象中是否有 typeDetail屬性,如果有,則表示該方法最終是根據 "Product.goods.typeDetail" 的值進行查詢;如果沒有該屬性,則繼續按照第三步的規則從右往左截取,最終表示根據 "Product.goods.type.detail" 的值進行查詢。

不過這種解析規則不是完美的,也存在bug,不注意可能會掉到這個坑里,比如Product中有一個屬性叫goods,同時還有一個屬性叫goodsType,這時在解析時會出現混亂,不過可以在屬性之間加上 "_"來解決這個問題,注意:"_"是加在查詢方法上的,不是加在屬性名上的;比如 "findByGoods_TypeDetail()" (當Product中不存在goods_TypeDetail時,是給解析器說明Goods為一個對象)或"findByGoodsType_Detail()"(當Product中不存在goodsType_Detail時,是給解析器說明GoodsType為一個對象)。

查詢時,很多時候需要同時使用多個屬性進行查詢,而且查詢的條件也各不相同,Spring Data JPA 為此提供了一些條件查詢的關鍵字,我把常用的都整理了一下,如下表:

關鍵字

對應SQL關鍵字

示例

列名

根據列名查詢

findByName(String name);自動解析findBy后面的列名,然后根據列名查詢。

In

等價于SQL 中的 in

findByNameIn(Collection<String> nameList) ;參數可以是集合、數組、不定長參數;

Like

等價于SQL 中的 like

findByNameLike(String name);

NotLike等價于SQL 中的 not likefindByNameNotLike(String name);

And

等價于SQL 中的 and

findByNameAndPwd(String name, String pwd);

Or

等價于SQL 中的 or

findByIdOrCode(String id, String code);

Between

等價于SQL 中的 between

findByNumBetween(int max, int min);

OrderBy

等價于SQL 中的 order by

findByNameOrderByNumAsc(String name);

IsNull

等價于SQL 中的 is null

findByNameIsNull();

IsNotNull等價于SQL 中的 is not nullfindByNameIsNotNull();
NotNull等價于SQL 中的 is not nullfindByNameNotNull();--和IsNotNull 一樣,建議使用IsNotNull
Not等價于SQL 中的 ! =findByNameNot(String name);
NotIn等價于SQL 中的 not infindByNameNotIn(Collection<String> nameList) ;參數可以是集合、數組、不定長參數;
LessThan等價于SQL 中的 <findByNumLessThan(int num);

GreaterThan

等價于SQL 中的 >

findByNumGreaterThan(int num);

二、使用 @Query 創建查詢

1、使用 @Query 提供的位置編號查詢:格式為":位置編號",然后方法中的參數按 JPQL 查詢語句的位置編號順序書寫。 如下:

public interface ProductDao extends Repository<Product , Long> {  
@Query("select * from Product p where p.id= ?1") 
public Product findById(Long id); 
 
@Query("select * from Product p where p.type = ?1 and p.name =?2") 
public Page<Product> findByTypeAndName( 
    Integer type,String name,Pageable pageable); 
}

2、使用@Query 命名參數查詢:格式為": 變量",同時在方法的參數前面使用 @Param 將方法參數與JPQL中的命名參數對應。如下:

public interface ProductDao extends Repository<Product , Long> {  
@Query("from Product p where p.goodsName= :name") 
public Product findByGoodsName(@Param("name")String name);  
@Query("from Product p where p.num < :num") 
public Page<Product> findByNumLessThan( 
    @Param("num")Integer num,Pageable pageable); 
}

3、 使用 @Modifying 將查詢操作標識為更新操作:在使用 @Query 的同時使用 @Modifying ,這樣會生成一個更新的操作,而非查詢。如下:

 @Query("update Product p set p.name = ?1 where p.id = ?2") 
@Modifying 
public int updateName(String name, int id);

JPA 常用查詢方法記錄

以這張表為例:

+-------------+--------------+------+-----+-------------------+----------------+
| Field       | Type         | Null | Key | Default           | Extra          |
+-------------+--------------+------+-----+-------------------+----------------+
| id          | int(11)      | NO   | PRI | NULL              | auto_increment |
| role        | varchar(45)  | NO   |     | NULL              |                |
| permissions | varchar(512) | NO   |     | NULL              |                |
| create_time | datetime     | NO   |     | CURRENT_TIMESTAMP |                |
| status      | varchar(45)  | NO   |     | NULL              |                |
| role_name   | varchar(45)  | NO   |     | NULL              |                |
+-------------+--------------+------+-----+-------------------+----------------+

CrudRepository 默認帶的查詢方法

如何理解Spring?Data?JPA查詢方式及方法名查詢規則

@Repository
public interface RoleRepository extends CrudRepository<RoleData, Integer> {
}  
@Entity
@Table(name = "role", catalog = "message_push")
public class RoleData implements java.io.Serializable {
 
    @Id
    @GeneratedValue
    private Integer id; 
    private String role; 
    private String permissions; 
    private Long create_time; 
    private Integer status; 
// getter setter 構造函數從略 
}

簡單的擴展-以字段為關鍵字進行查詢

list<RoleData> findByXXX(xxx) 其中 XXX 對應數據庫中的字段,例如:

@Repository
public interface RoleRepository extends CrudRepository<RoleData, Integer> { 
    List<RoleData> findByRole(String role);
    List<RoleData> findByStatus(String status);
}

還可以多字段AND 查詢:

@Repository
public interface RoleRepository extends CrudRepository<RoleData, Integer> { 
    List<RoleData> findByRoleAndStatus(String role, String status);
}

在 application.properties 中加入以下配置 spring.jpa.show-sql=true 可以看到SQL語句:

Hibernate: select roledata0_.id as id1_0_, roledata0_.create_time as create_t2_0_, roledata0_.permissions as permissi3_0_, roledata0_.role as role4_0_, roledata0_.status as status5_0_ from message_push.role roledata0_ where roledata0_.role=? and roledata0_.status=?

當然 or 也是可以:

List<RoleData> findByRoleOrStatus(String role, String status);

Hibernate: select roledata0_.id as id1_0_, roledata0_.create_time as create_t2_0_, roledata0_.permissions as permissi3_0_, roledata0_.role as role4_0_, roledata0_.status as status5_0_ from message_push.role roledata0_ where roledata0_.role=? or roledata0_.status=?

使用@Query 進行復雜查詢

例如:

@Query(value = "select * from role where role = ?1", nativeQuery = true)
List<RoleData> searchByRole(String role);

或 sql in 用法

@Query(value = "select * from role where role in (?1) and status = 'valid'", nativeQuery = true)
List<RoleData> searchByRoleList(List<String> targetList);

又或 sql like 用法:

@Query(value = "select * from role where role like %?1%", nativeQuery = true)
List<RoleData> searchByRole(String keyWord);

使用 Specification 進行復雜查詢

先來看一下 JpaSpecificationExecutor 接口

如何理解Spring?Data?JPA查詢方式及方法名查詢規則

以 findAll(Specification<T>) 為例進行說明:

Specification<T> 可以理解為一個查詢條件。findAll 以這個條件為基準進行查詢,也就是我們在sql 里寫的 whre xxx 轉為 Specification 來寫。

首先要讓我們的 repository 繼承 JpaSpecificationExecutor

@Repository
public interface RoleRepository extends CrudRepository<RoleData, Integer>, JpaSpecificationExecutor<RoleData> {

接下來,將這個查詢 [ select * from role where role like '%a%' ] 轉為一個簡單的 Specification。

final Specification<RoleData> spec = new Specification<RoleData> () {
            @Override
            public Predicate toPredicate(Root<RoleData> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                Predicate predicate = criteriaBuilder.like(root.get("role"), "%a%");
                return predicate;
            }
        };

然后直接按如下方式調用即可:

roleRepository.findAll(spec);

Specification 里又衍生出了好幾個類,分別介紹一下:

Predicate

因為我們實現 Specification 接口時,只需要實現 Predicate toPredicate() 方法。而 Specification 上文中我們當做搜索條件來理解了,那么也可以簡單的把 Predicate 視為搜索條件。

CriteriaBuilder

用于構建搜索條件 Predicater 的。

回想一下SQL搜索條件怎么寫

where attribute = xx
where attribute > xx 
where attribute < xx
where attribute like %xx%

注意這里有三要素:

  • attribute 搜索指定的數據庫字段

  • 操作符 大于 小于 等于

  • 具體數據

CriteriaBuilder提供了一系列靜態方法構建這三要素。

比如

  • CriteriaBuilder.like(數據庫字段, 具體數據)

  • CriteriaBuilder.equal(數據庫字段, 具體數據)

其中 數據庫字段 不能直接寫字符串,需要下一個工具類 Root 的 get 方法獲取。

Root

root.get( String attributeName ) 參數 attributeName 就是數據庫里的字段名

現在相信讀者可以理解 我們剛才寫的 那個完整的 Specification了。

再下來再上一個稍微復雜點的例子:

[  select * from role where role like '%a%' and (id > 11 or id < 8) ]
final Specification<RoleData> spec = new Specification<RoleData> () {
            @Override
            public Predicate toPredicate(Root<RoleData> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                Predicate roleLikeaPredicate = criteriaBuilder.like(root.get("role"), "%a%");
                Predicate idLessThan8Predicate = criteriaBuilder.lessThan(root.get("id"), 8);
                Predicate idGreaterThan12Predicate = criteriaBuilder.greaterThan(root.get("id"), 11);
 
                Predicate idCombindedPredicate = criteriaBuilder.or(idLessThan8Predicate, idGreaterThan12Predicate);
                Predicate predicate = criteriaBuilder.and(idCombindedPredicate, roleLikeaPredicate); 
                return predicate;
            }
        };

其實也很簡單,就是多了 criteriaBuilder.or criteriaBuilder.and 來把多個 Predicate 合成一個新的 Predicate

最后一個例子:

可以通過root.get(xx).in(List<> list) 也是可以直接返回 Predicate 的

 
        final Specification<RoleData> spec2 = new Specification<RoleData> () {
            @Override
            public Predicate toPredicate(Root<RoleData> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<String> alist = new ArrayList<String>();
                alist.add("admin");
                Predicate predicate = root.get("role").in(alist);
                return predicate;
            }
        };

關于如何理解Spring Data JPA查詢方式及方法名查詢規則就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

平原县| 宜春市| 容城县| 安庆市| 泰来县| 涿州市| 富蕴县| 饶阳县| 利川市| 木里| 徐汇区| 大理市| 德安县| 宜良县| 克什克腾旗| 余姚市| 加查县| 江华| 长海县| 太仓市| 双辽市| 北票市| 安远县| 开平市| 垦利县| 奉新县| 南涧| 班戈县| 淮阳县| 穆棱市| 奎屯市| 澄迈县| 贞丰县| 滁州市| 金昌市| 建始县| 永宁县| 舞钢市| 丁青县| 阿坝县| 沙雅县|