jpa 常用查詢方法記錄
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 預設帶的查詢方法
-
@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 介面
以 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;
-
}
-
};
還有很多沒講,後續有時間再補充吧。
https://blog.csdn.net/wuzhong8809/article/details/84873938