Repository接口及查詢接口規范


Repository接口

  1. 是什么
    1. Repository是一個空接口,即:是一個標記接口,表示任何繼承它的接口都是倉庫接口類
    2. 若我們繼承了Repository,則該接口會被Ioc容器表示為一個Repository Bean,放入到IOC容器中,進而可以在該接口中定義滿足一定規范的方法
    3. 實際上也可以通過@RepositoryDefinition(domainClass = Person.class, idClass = Long.class)來替代繼承Repository接口
  2. 子接口
    1. CrudRepository:繼承Repository,實現一組CURD相關的方法
    2. PagingAndSortingRespository:繼承CrudRepository,實現了一組分頁排序相關的方法
    3. JpaRepository:繼承PagingAndSortingRespository,實現了一組JPA規范相關的方法
    4. 自定義的XxxRepository:需要繼承JpaRepository,這樣該接口就具備了通用的數據訪問控制層的能力
    5. JpaSpecificationExecutor:不屬於Repository體系,實現一組 JPA Criteria 查詢相關的方法

Repository 查詢方法定義規范

1. 查詢方法

  1. 方法必須以find|read|get開頭

  2. 涉及查詢條件時,條件的實行用條件關鍵字連接,

    • 注意:條件屬性需要首字母大寫
  3. 支持屬性的級聯查詢

    1. 若當前類有符合條件的屬性,會優先使用屬性,而不是使用級聯屬性

    2. 若要使用級聯屬性,則屬性之間用 _ 連接。而為了避免歧義,推薦使用 _ 分隔的寫法。如:

      // Address類
      @Entity
      @Table(name = "t_address")
      public class Address implements Serializable {
          private static final long serialVersionUID = -682608034116202529L;
      
          @Id
          @GeneratedValue(strategy = GenerationType.IDENTITY)
          private Long id;
          private String province;
          private String city;
      
          @ManyToOne
          @JoinColumn(name = "person_id")
          private Person person;
      }
      
      // Person類
      @Entity
      @Table(name = "t_person")
      public class Person implements Serializable {
          private static final long serialVersionUID = -5964437048712784999L;
      
          @Id
          @GeneratedValue(strategy = GenerationType.IDENTITY)
          private Long id;
          private String name;
          private Integer age;
          private String gender;
          private String email;
          @Column(name = "address_id")
          // 搗亂的字段
          private Long addressId;
      
          @OneToMany(mappedBy = "person")
          private Set<Address> address = new HashSet<>();
      }
      
      // PersonDao中的getByAddress_Id必須使用 _ 分隔,而不能直接寫 getByAddressId
      public interface PersonDao extends Repository<Person, Long> {
          List<Person> getByNameLike(String name);
          Person getByAddress_Id(Long id);
      }
      
    3. 缺點:

      • 方法名很長
      • 不能用於子查詢

2. 注解

  1. @Query

    1. 可以執行自定義的JPQL語句以更靈活的查詢

      // 查詢id最大的那個person
      @Query("from Person p1 where p1.id = (select max(p2.id) from Person p2)")
      Person getPersonByMaxId();
      
    2. 注解傳遞參數

      1. 使用占位符:參數順序必須和JPQL中的順序一致

        @Query("from Person p where p.name = ?1 and p.gender = ?2")
        Person query_getPersonByNameAndGender(String name, String gender);
        
      2. 使用命名參數:這種寫法可以隨便設置參數順序

        @Query("from Person p where p.name = :name and p.age = :age")
        Person query_getPersonByNameAndAge(@Param("age") Integer age, @Param("name") String name);
        
        • @Param:org.springframework.data.repository.query.Param;
    3. spring data允許在占位符上添加%(適用於模糊查詢like:%占位符%

    4. @Query支持原生sql查詢

      @Query(value = "select count(1) from t_person", nativeQuery = true)
      Long getTotal();
      
  2. @Modifying:可以使用該注解來實現通過JPQL修改和刪除(JPQL不支持添加)

    @Modifying
    @Query(value = "update Person p set p.name = ?1, p.age = ?2 where p.id = ?3")
    void updatePerson(String name, Integer age, Long id);
    
    • 注意:更新和刪除操作需要事務支持
    • 在@Query中編寫JPQL語句,但是必須添加@Modifying進行修飾來告訴JPA這是修改的操作
    • 為什么@Query可以執行呢?
      • 所有的Repository方法都有一個事務,但是卻是只讀事務

3. CRUDRepository

  • 這個接口提供了基本增刪改查方法

4. PagingAndSortingRepository

  • 該接口提供了排序和分頁的方法:方法的參數Pagable里面包含的有Sort

  • 測試

    1. 測試分頁:pageNum(頁碼)從0開始計數

      @Test
      public void test08() {
          Pageable pageable = PageRequest.of(0, 10);
          Page<Person> personPage = personDao.findAll(pageable);
          System.out.println("總記錄條數:" + personPage.getTotalElements());
          System.out.println("總頁數:" + personPage.getTotalPages());
          System.out.println("當前頁:" + personPage.getNumber());
          System.out.println("當前頁內容(數據):" + personPage.getContent());
          System.out.println("當前頁記錄數:" + personPage.getNumberOfElements());
      }
      
    2. 測試排序

      @Test
      public void test09() {
          Sort sort = Sort.by(Sort.Direction.DESC, "id");
          Iterable<Person> persons = personDao.findAll(sort);
          persons.forEach(System.out::println);
      }
      
    3. 測試分頁排序

      @Test
      public void test10() {
          // Pageable pageable = PageRequest.of(0, 10, Sort.Direction.DESC, "age", "id");
          // Sort sort = Sort.by(Sort.Direction.DESC, "age", "id");
          Sort.Order order1 = new Sort.Order(Sort.Direction.DESC, "age");
          Sort.Order order2 = new Sort.Order(Sort.Direction.ASC, "name");
          Sort sort = Sort.by(order1, order2);
          Pageable pageable = PageRequest.of(0, 10, sort);
          Page<Person> personPage = personDao.findAll(pageable);
          personPage.forEach(System.out::println);
      }
      

5. JpaRepository

  • JpaRepository中定義了一些新的方法,最主要是批量操作的方法

  • 方法
    2. <S extends T> List<S> saveAll(Iterable<S> var1):批量保存

    1. void flush():刷新。同步Jpa緩存和數據庫

    2. <S extends T> S saveAndFlush(S var1):相當於JPA的merge方法

    3. void deleteInBatch(Iterable<T> var1):批量刪除

    4. void deleteAllInBatch():批量刪除所有

6. JpaSpecificationExecutor

  • 通過查詢條件查詢

  • 方法

    1. Optional<T> findOne(@Nullable Specification<T> spec):根據條件查詢

    2. findAll:查詢所有

      • List<T> findAll(@Nullable Specification<T> spec):根據條件查詢所有

      • Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable):根據條件分頁[排序]

      • List<T> findAll(@Nullable Specification<T> spec, Sort sort):根據條件排序

    3. long count(@Nullable Specification<T> spec):查詢數量

  • Specification接口:

    Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder);
    
    1. 該接口通常使用匿名內部類
    2. Predicate 代表查詢條件
    3. Root 代表查詢的實體類對象
    4. CriteriaQuery 可以從中查詢到 root 對象,還可以用來添加查詢條件,還可以結合EntityManager獲取最終查詢的TypeQuery對象
    5. CriteriaBuilder 用於創建Criteria相關對象的工廠,當然可以從中獲取到 Predicate 對象

本節代碼:點擊此處


免責聲明!

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



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