spring-data-jpa簡單使用(二)
1:使用spring-data-jpa很簡單,只需要在dao層繼承repository介面即可。那麼repository介面是什麼呢?
可以看到repository介面下面什麼都沒有,這表明它是一個標記介面。標記介面的作用的什麼?標記介面的作用是把當前類納入到spring的容器中,繼承了這個類你會發現
這個標記我想使用idea的同志們都不會陌生的,因為這個表明,當前的類已經被納入到spring容器中,可以被spring掃描到。那麼,除了繼承Repository這個介面,還可以怎麼做 -> 在介面上加上@RepositoryDefinition註解
RepositoryDefinition註解中有兩個屬性(domainClass,idClass)一個標識實體類的位元組碼型別和主鍵的位元組碼型別
但是我們一般不用這個註解,這裡我們瞭解一下知道他是怎麼搞的就行:無非就是用了spring的aop和反射來實現的。
下面我們來看看spring-data-jpa有哪些介面
那麼查詢方法的規則和使用又是怎麼樣的呢?
在介面下面定義的方法必須遵循這些規則
上程式碼:
1:查詢出名字以胡開頭,並且年齡小於25
@Test public void test1(){ // 查詢出名字以胡開頭,並且年齡小於25 List<User> users = userRepository.findByNameLikeAndAgeLessThan("胡%",25); users.forEach(p -> System.out.println(p.getName() + " ,年齡" + p.getAge())); }
2:使用原生的sql進行查詢
@Query(value = "select * from user u where u.name like ?1% and age > ?2",nativeQuery = true)
List<User> findUser(String name,int age);
需要使用@Query註解和nativeQuery屬性
3: 不使用原生的sql進行查詢
@Query(value = "select u from User u where u.salary > ?1") List<User> findSalary(double salary);
from後面就不能寫表名了,只能寫表對應的對映名稱 ?1代表佔位符,當前你也可以使用:如下
@Query(value = "select u from User u where u.id = :id")
User findUser(@Param("id")long id);
這有一個誤區:就是冒號後面對應的值應該和@Param裡面的值一致,否則或報錯
@Query(value = "select u from User u where u.id = :idd")
User findUser(@Param("idd")long id);
這是正確的,註解裡面的值和冒號後面的值對應。下面是錯誤的:
@Query(value = "select u from User u where u.id = :idd")
User findUser(@Param("id")long idd);
4:修改查詢
@Modifying
@Query(nativeQuery = true,value = "update user u set u.address = ?2 where u.id = ?1")
void update(Long id,String address);
需要@Modifying註解和@Query註解和@Transactional註解(放在service層) 缺一不可.
5:關聯查詢什麼之類的就不用我多嘴了吧 直接@Query註解加上nativeQuery屬性搞起來,原生sql別說你不會哈!!!
分頁排序:
這裡需要兩個物件:Sort和PageRequest
程式碼如下:
public List<User> getUsers(){
// 安裝薪資降序
Sort sort = new Sort(Sort.Direction.DESC,"salary");
// 每頁大小十頁
PageRequest pageRequest = PageRequest.of(0,10,sort);
List<User> users = userRepsoitory.findAll(pageRequest).getContent();
return users;
}
具體方法點進去看api需要什麼引數
那麼?更復雜點的動態sql分頁排序查詢,spring-data-jpa能解決嗎?我們知道mybatis可以在xml檔案中使用if,for之類的標籤來判斷,構造動態sql;那spring-data-jpa怎麼構建:
這個時候就需要一個強大的物件出馬:
Specification 和JpaSpecificationExecutor<T>
程式碼如下:
public List<User> conditionalQuery(User user){
Specification<User> specification = new Specification<User>() {
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
// root:可用從root中拿到User的屬性
// cq:用來查詢
// cb:用來構造查詢條件
List<Predicate> predicates = new ArrayList<>();
if (!StringUtils.isBlank(user.getName())) {
predicates.add(cb.like(root.get("name"),user.getName() + "%"));
}
if (user.getAge() > 0) {
predicates.add(cb.gt(root.get("age"),user.getAge()));
}
if (user.getSalary() > 0) {
predicates.add(cb.gt(root.get("salary"),user.getSalary()));
}
Predicate result = cb.and(predicates.toArray(new Predicate[predicates.size()]));
return result;
}
};
// 這個排序分頁還記得怎麼操作嗎?
PageRequest pageRequest = PageRequest.of(0,10,Sort.Direction.DESC,"salary");
List<User> users = userRepsoitory.findAll(specification, pageRequest).getContent();
return users;
}
}
dao層需要繼承JpaSpecificationExecutor<User>,然後用JpaSpecificationExecutor<User>的findAll方法;
結果如下:
按薪水降序:
[
{
"id": 5,
"name": "胡歌",
"age": 30,
"salary": 2100000,
"address": "上海"
},
{
"id": 17,
"name": "胡歌",
"age": 27,
"salary": 2100000,
"address": "上海"
},
{
"id": 18,
"name": "胡歌",
"age": 30,
"salary": 2100000,
"address": "上海"
},
{
"id": 21,
"name": "胡歌",
"age": 27,
"salary": 2100000,
"address": "上海"
},
{
"id": 19,
"name": "胡歌",
"age": 26,
"salary": 21000,
"address": "上海"
},
{
"id": 20,
"name": "胡歌",
"age": 19,
"salary": 18000,
"address": "上海"
}
]
總結:
1:簡單的查詢可以直接呼叫JpaRepository的方法和其命名規範查詢
2:關聯查詢可以使用@Query註解加nativeQuery屬性
3:動態sql分頁排序查詢可以使用Specification和JpaSpecificationExecutor介面