Spring Data Jpa 自定義查詢定義規則 及事務、分頁


關於SpringData JPA查詢的定義

  1. 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開始,例 ?1,?2
    @Query(nativeQuery = false,value = " SELECT p FROM User p WHERE id = ?1")
    User readId(Integer id);
  1. [:][],[...:][參數名],參數名必須是實體的屬性名,並且方法參數上加上對應的注解@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);

分頁對象

  1. 要求自定義的Repository必須繼承了PagingAndSortingRepository或者他的子類JpaRepository

  2. 分頁對象是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());
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM