關於SpringData JPA查詢的定義
- spring data 對於定義方法的查詢策略
查詢策略是spring data 根據方法名稱取解析用戶的查詢意圖,
第一種,根據方法的命名規則解析,
第二種是通過Query去解析,
如果兩種同時存在時,springdata按照那種解析方法名,這就是spring data的查詢策略,查詢策略可以在jpa:repositorys/ 屬性query-lookup-strategy 配置
CREATE: 通過解析方法的名稱來創建查詢,也就是下面的規則1
USE_DECLARED_QUERY:根據定義好的語句去查詢,如果找不到,拋出異常信息。查詢語句定義在某個注解或者方法上。
CREATE_IF_NOT_FOUND:優先查詢方法上是否有定義好的查詢語句,如果沒有,則按照方法名稱解析,這是默認的策略。
public interface UserRepository extends JpaRepository<User,Integer>, JpaSpecificationExecutor<User> {
//根據springData的關鍵字命名方法名稱,可以不用寫實現類
List<User> findByNameAndAge(String name, Integer age);
List<User> findByNameLikeAndAge(String name, Integer age);
//@Query注解里面寫JPQL語句,定義查詢
@Query(nativeQuery = false,value = " SELECT p FROM User p WHERE id = ?1")
User readId(Integer id);
//Query注解也可以定義SQL語句,只要將nativeQuery屬性改為true
@Query(nativeQuery = true, value = "select name from user where id = :id")
String findNamebyId(@Param("id")Integer id);
//@Modifying修飾方法,告知SpringData,這是一個UPATE或者DELETE操作
//在service層的方法上添加事務操作
@Modifying
@Query(nativeQuery = true,value = "update user set name = ?1 where id = ?2 ")
int updateUserNameById(String name,Integer id);
}
規則1:根據SpringData JPA的關鍵字定義方法名,方法的參數順序和關鍵字的順序一致,名稱可以不一致。
Spring Data JPA對方法名稱進行解析的時候,會將一些無用的前綴名自動去除,比如find、findBy、read、readBy,然后根據關鍵字解析成對應JPQL語句。也要注意方法的參數順序和定義的關鍵字的順序一致。
規則2:定義方法時候,上面加上注解@Query,默認nativeQuery是false,此時value填入的是JPQL語句,修改nativeQuery是true,就能夠寫入SQL語句
//@Query注解里面寫JPQL語句,定義查詢
@Query(nativeQuery = false,value = " SELECT p FROM User p WHERE id = ?1")
User readId(Integer id);
//Query注解也可以定義SQL語句,只要將nativeQuery屬性改為true
@Query(nativeQuery = true, value = "select name from user where id = :id")
String findNamebyId(@Param("id")Integer id);
注意參數注入的方式有兩種:
[?][方法參數索引]
,索引從1開始,例?1
,?2
@Query(nativeQuery = false,value = " SELECT p FROM User p WHERE id = ?1")
User readId(Integer id);
[:][]
,[...:][參數名]
,參數名必須是實體的屬性名,並且方法參數上加上對應的注解@Param("xxx")
和@Param('yyy')
@Query(nativeQuery = true, value = "select name from user where id = :id")
String findNamebyId(@Param("id")Integer id);
@Modify和事務
可以通過JPQL語句定義update/delete,此時在@Query注解中定義,必須加上@Modify,告訴spring data 這是一個update/delete操作。
update/delete操作需要事務支持,必須在service層,添加事務,因為spring data,默認情況下每個方法是只讀事務,不能完成update/delete操作。
public interface UserRepository extends JpaRepository<User,Integer>, JpaSpecificationExecutor<User> {
//根據springData的關鍵字命名方法名稱,可以不用寫實現類
List<User> findByNameAndAge(String name, Integer age);
List<User> findByNameLikeAndAge(String name, Integer age);
//@Query注解里面寫JPQL語句,定義查詢
@Query(nativeQuery = false,value = " SELECT p FROM User p WHERE id = ?1")
User readId(Integer id);
//Query注解也可以定義SQL語句,只要將nativeQuery屬性改為true
@Query(nativeQuery = true, value = "select name from user where id = :id")
String findNamebyId(@Param("id")Integer id);
//@Modifying修飾方法,告知SpringData,這是一個UPATE或者DELETE操作
//在service層的方法上添加事務操作
@Modifying
@Query(nativeQuery = true,value = "update user set name = ?1 where id = ?2 ")
int updateUserNameById(String name,Integer id);
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository repository;
//對於SpringData jpa的update或者delete操作,必須在service層使用事務,直接使用倉庫的方法會報錯
//另外,SpringData jpa 的 JPQL語法不支持insert
@Transactional(propagation = Propagation.REQUIRED)
public int updateUserNameById(String name,Integer id){
return repository.updateUserNameById(name,id);
}
}
@RunWith(value = SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class SpringDataTest {
@Autowired
private UserRepository repository;
@Autowired
private UserService service;
@Test
public void test(){
service.updateUserNameById("張三",1);
}
}
分頁和模糊查詢
模糊查詢
需要注意的是%%
外面不需要再加上''
//模糊查詢
@Query(nativeQuery = true,value = " select * from user where name like %?1% ")
User findUserByLikeName(String name);
分頁對象
-
要求自定義的Repository必須繼承了PagingAndSortingRepository或者他的子類JpaRepository
-
分頁對象是Pageable接口的實現類PageRequest
public class PageRequest implements Pageable, Serializable {
private static final long serialVersionUID = 8280485938848398236L;
private final int page;//頁碼,從0開始,0表示第一頁,1表示第二頁,以此類推
private final int size;//每頁顯示的記錄數
private final Sort sort;//排序規則
Sort對象,定義排序規則,常用的是下面這種構造函數,支持可變參數的
public Sort(Sort.Direction direction, String... properties) {
this(direction, (List)(properties == null ? new ArrayList() : Arrays.asList(properties)));
}
定義分頁查詢,只需要將查詢的參數和分頁對象作為參數。
Page<User> findByNameLike(String str , Pageable pageable);
@RunWith(value = SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class SpringDataTest {
@Autowired
private UserRepository repository;
@Test
public void test(){
/**
* SpringData jpa 的分頁
* Pageable接口的實現類是PageRequest,Page接口的實現類是PageImpl。
*/
Pageable page = new PageRequest(0,2,new Sort(Sort.Direction.DESC,"id"));
Page<User> personList = repository.findByNameLike("張%",page);
System.out.println("總記錄數" + personList.getTotalElements());
System.out.println("當前第幾頁: " + (personList.getNumber() + 1));
System.out.println("總頁數: " + personList.getTotalPages());
System.out.println("當前頁面的記錄數:" + personList.getContent());
System.out.println("當前頁面的記錄數: " + personList.getNumberOfElements());
}
}