Written By : Nguyễn Văn Linh
Gmail : Linhthai130100@gmail.com
1. Giới Thiệu
Đối với các truy vấn đơn giản , thật dễ dàng để tìm ra truy vấn chỉ bằng cách nhìn vào tên các phương thức tương ứng trong các đoạn mã.
Vậy khi chúng ta muốn tự custom hay là lựa chọn các câu truy vấn theo các phương thức mà bản thân chúng ta tự đặt ra theo bài toán của mình thì phải làm như thế nào?
Trong hướng dẫn này , tôi sẽ cũng các bạn khám phá cách Spring Data Jpa tận dụng ý tưởng này dưới dạng một quy ước đặt tên phương thức
Link bài viết tham khảo : Derived Query Methods in Spring Data JPA Repositories
2. Cấu trúc của phương thức truy vấn có nguồn gốc trong Spring
Tên phương thức xuất phát từ 2 phần chính được phân tách bằng từ khóa By
đầu tiên :
List<User> findByName(String name)
Phần đầu tiên - chẳng hạn như find là người giới thiêu , và phần còn lại - chằng hạn như ByName - là tiêu chí
Spring Data Jpa hỗ trợ find , read , query , count and get . Vì vậy , chúng ta có thể đã thực hiện queryByName và Spring Data sẽ hoạt động giống nhau.
Chúng ra cũng có thể sử dụng Distinct
, First
or Top
cùng để loại bỏ các bản sao hoặc giới hạn tập hợp kết quả của chúng tôi :
List<User> findTop3ByAge()
Phần tiêu chí chứa các biểu thức điều kiện cụ thể của thực thể của truy vấn. Chúng tôi có thể sử dụng các từ khóa điều kiện cùng với tên thuộc tính của thực thể.
Chúng ta cũng có thể nối các biểu thức với And
và Or
, như chúng ta sẽ thấy trong giây lát.
3. Ứng dụng mẫu
Đầu tiên, tất nhiên chúng ta sẽ cần một ứng dụng sử dụng Spring Data JPA .
Trong ứng dụng đó, hãy xác định một lớp thực thể:
@Table(name = "users")
@Entity
class User {
@Id
@GeneratedValue
private Integer id;
private String name;
private Integer age;
private ZonedDateTime birthDate;
private Boolean active;
// standard getters and setters
}
Hãy cũng xác định một kho lưu trữ.
Nó sẽ mở rộng JpaRepository , một trong những loại Spring Data Repository :
interface UserRepository extends JpaRepository<User, Integer> {}
Đây là nơi chúng tôi sẽ đặt tất cả các phương thức truy vấn bắt nguồn của chúng tôi.
4. Từ khoá Điều kiện Bình đẳng
Bình đẳng chính xác là một trong những điều kiện được sử dụng nhiều nhất trong các truy vấn. Chúng tôi có một số tùy chọn để thể hiện các toán tử = hoặc IS trong truy vấn.
Chúng tôi có thể chỉ thêm tên thuộc tính mà không cần bất kỳ từ khóa nào để có điều kiện đối sánh chính xác:
List<User> findByName(String name);
Và chúng ta có thể thêm Is hoặc Equals để dễ đọc:
List<User> findByNameIs(String name);
List<User> findByNameEquals(String name);
Khả năng đọc thêm này rất hữu ích khi chúng ta cần thể hiện sự bất bình đẳng thay vào đó:
List<User> findByNameIsNot(String name);
Điều này khá dễ đọc hơn findByNameNot (String) !
Vì đẳng thức rỗng là một trường hợp đặc biệt, chúng ta không nên sử dụng toán tử =. Spring Data JPA xử lý các tham số rỗng theo mặc định. Vì vậy, khi chúng ta chuyển một giá trị null cho một điều kiện bình đẳng, Spring sẽ diễn giải truy vấn là IS NULL trong SQL được tạo.
Chúng tôi cũng có thể sử dụng từ khóa IsNull để thêm tiêu chí IS NULL vào truy vấn:
List<User> findByNameIsNull();
List<User> findByNameIsNotNull();
Lưu ý rằng cả IsNull và IsNotNull đều không yêu cầu đối số phương thức.
Ngoài ra còn có hai từ khóa khác không yêu cầu bất kỳ đối số nào.
Chúng ta có thể sử dụng các từ khóa True và False để thêm các điều kiện bình đẳng cho các kiểu boolean :
List<User> findByActiveTrue();
List<User> findByActiveFalse()
Tất nhiên, đôi khi chúng ta muốn điều gì đó khoan dung hơn là bình đẳng chính xác, vì vậy hãy xem chúng ta có thể làm gì khác.
5. Từ khóa điều kiện tương tự
Khi chúng tôi cần truy vấn kết quả với một mẫu thuộc tính, chúng tôi có một vài tùy chọn.
Chúng tôi có thể tìm các tên bắt đầu bằng một giá trị bằng StartWith :
List<User> findByNameStartingWith(String prefix);
Đại khái, điều này được dịch thành "WHERE tên LIKE " giá trị% " ".
Nếu chúng ta muốn các tên kết thúc bằng một giá trị, thì EndingWith là những gì chúng ta muốn:
List<User> findByNameEndingWith(String suffix);
Hoặc chúng ta có thể tìm tên nào chứa giá trị bằng Containing
List<User> findByNameContaining(String infix);
Lưu ý rằng tất cả các điều kiện ở trên được gọi là biểu thức mẫu xác định trước. Vì vậy, chúng ta không cần thêm toán tử % vào bên trong đối số khi các phương thức này được gọi.
Nhưng giả sử chúng ta đang làm một cái gì đó phức tạp hơn. Giả sử chúng ta cần tìm nạp những người dùng có tên bắt đầu bằng a , chứa b và kết thúc bằng c .
Để làm được điều đó, chúng ta có thể thêm LIKE của chính mình bằng từ khóa Like :
List<User> findByNameLike(String likePattern);
Và sau đó chúng ta có thể đưa vào mẫu LIKE của mình khi chúng ta gọi phương thức:
String likePattern = "a%b%c";
userRepository.findByNameLike(likePattern);
Vậy là đủ về tên cho bây giờ. Hãy thử một số giá trị khác trong Người dùng .
6. Từ khóa điều kiện so sánh
Hơn nữa, chúng ta có thể sử dụng các từ khóa LessThan
và LessThanEqual
để so sánh các bản ghi với giá trị đã cho bằng cách sử dụng các toán tử < và <= :
List<User> findByAgeLessThan(Integer age);
List<User> findByAgeLessThanEqual(Integer age);
Trong trường hợp ngược lại, chúng ta có thể sử dụng các từ khóa GreaterThan
và GreaterThanEqual
:
List<User> findByAgeGreaterThan(Integer age);
List<User> findByAgeGreaterThanEqual(Integer age);
Hoặc chúng tôi có thể tìm thấy những người dùng ở giữa hai độ tuổi với Between
:
List<User> findByAgeBetween(Integer startAge, Integer endAge);
Chúng tôi cũng có thể cung cấp một tập hợp các độ tuổi để so khớp với việc sử dụng In
:
List<User> findByAgeIn(Collection<Integer> ages);
Vì chúng tôi biết ngày sinh của người dùng, chúng tôi có thể muốn truy vấn những người dùng sinh trước hoặc sau một ngày nhất định.
Chúng tôi sẽ sử dụng Before
and After
cho việc đó:
List<User> findByBirthDateAfter(ZonedDateTime birthDate);
List<User> findByBirthDateBefore(ZonedDateTime birthDate);
7. Biểu thức nhiều điều kiện
Chúng tôi có thể kết hợp bao nhiêu biểu thức nếu chúng tôi cần bằng cách sử dụng các từ khóa Or
và And
:
List<User> findByNameOrBirthDate(String name, ZonedDateTime birthDate);
List<User> findByNameOrBirthDateAndActive(String name, ZonedDateTime birthDate, Boolean active);
Thứ tự ưu tiên là AND
sau đó là OR
, giống như Java.
Mặc dù Spring Data JPA không áp đặt giới hạn về số lượng biểu thức mà chúng ta có thể thêm vào, nhưng chúng ta không nên điên rồ ở đây. Tên dài khó đọc và khó duy trì. Đối với các truy vấn phức tạp, hãy xem chú thích @Query .
8. Sắp xếp kết quả
Tiếp theo, hãy xem xét việc sắp xếp.
Chúng tôi có thể yêu cầu người dùng được sắp xếp theo thứ tự bảng chữ cái theo tên của họ bằng OrderBy
:
List<User> findByNameOrderByName(String name);
List<User> findByNameOrderByNameAsc(String name);
Thứ tự tăng dần là tùy chọn sắp xếp mặc định, nhưng chúng ta có thể sử dụng Desc
để sắp xếp ngược lại:
List<User> findByNameOrderByNameDesc(String name);
9. findOne so với findById trong CrudRepository
Nhóm Spring đã thực hiện một số thay đổi lớn trong CrudRepository với Spring Boot 2.x. Một trong số đó là đổi tên findOne thành findById .
Trước đây với Spring Boot 1.x, chúng ta sẽ gọi findOne khi chúng ta muốn truy xuất một thực thể bằng khóa chính của nó:
User user = userRepository.findOne(1);
Kể từ Spring Boot 2.x, chúng ta có thể làm tương tự với findById :
User user = userRepository.findById(1);
Lưu ý rằng phương thức findById ()
đã được định nghĩa trong CrudRepository cho chúng tôi. Vì vậy, chúng ta không cần phải xác định nó một cách rõ ràng trong các kho lưu trữ tùy chỉnh mở rộng CrudRepository .
10. Kết luận
Trong bài viết này, chúng tôi đã giải thích cơ chế dẫn xuất truy vấn trong Spring Data JPA. Chúng tôi đã sử dụng các từ khóa điều kiện thuộc tính để viết các phương thức truy vấn dẫn xuất trong kho lưu trữ Spring Data JPA.
Bình luận