Parameter Opsional dalam Repositori Data Musim Semi

Setiap orang yang menggunakan Spring Data menghadapi situasi di mana Anda memiliki repositori untuk bekerja dengan suatu entitas dan Anda ingin menulis metode pencarian universal untuk mencari dengan seperangkat parameter yang dapat ditetapkan atau dilewati pengguna pada formulir pencarian. Implementasi dasar metode find di Spring Data menemukan entitas hanya dengan mempertimbangkan semua parameter, tidak memungkinkan Anda untuk mencari dengan set yang terbatas. Saya menemukan cara untuk mengatasi masalah ini dan membuat perpustakaan OpenSource untuk penggunaan cepat dalam proyek lain.

Untuk memahami masalah, mari kita bayangkan bahwa kita sedang membuat aplikasi notebook sederhana, di mana kita mendefinisikan entitas - Orang dengan id bidang, firstName, lastName, phoneNumber.

Person.java
@Entity @Data @AllArgsConstructor @NoArgsConstructor @EqualsAndHashCode(of = "id") public class Person { @Id private Long id; private String firstName; private String lastName; private String phoneNumber; } 


Misalkan kita harus menyediakan pencarian berdasarkan nama depan, nama belakang dan bagian dari nomor telepon atau dengan kombinasi dari parameter-parameter ini dan ingin metode pencarian tidak memperhitungkan parameter akun yang nilainya nol. Untuk mengatasi masalah ini, Anda dapat melakukan beberapa cara:

  1. Bekerja secara langsung dengan database melalui SQL, buat metode dalam layanan yang secara dinamis akan menghasilkan query SQL. Sesuatu seperti

    Kueri dinamis
      Iterable<Person> find(String firstName, String lastName, String phoneNumber) { List<String> where = new ArrayList(); List params = new ArrayList(); if(firstName != null) { params.add(firstName); where.add("first_name = ?"); } if(lastName != null) { params.add(lastName); where.add("last_name = ?"); } if(phoneNumber != null) { params.add(phoneNumber); where.add("phone_number = ?"); } String sql = "SELECT * FROM person " + (where.isEmpty() ? "" : " WHERE " + String.join(" AND ", where)); //  SQL  JDBCTemplate // ... } 

  2. Gunakan anotasi Permintaan untuk metode pencarian dengan parameter memeriksa null.

    @Query
      @Query("SELECT p FROM Person p " + "WHERE " + "(firstName = :firstName or :firstName is null) and " + "(lastName = :lastName or :lastName is null) and " + "(phoneNumber = :phoneNumber or :phoneNumber is null)" ) Iterable<Person> find( @Param("firstName") String firstName, @Param("lastName") String lastName, @Param("phoneNumber") String phoneNumber ); 


  3. Buat metode pencarian untuk semua kemungkinan kombinasi parameter dan panggil metode yang diinginkan setelah memeriksa parameter untuk null.

    Banyak metode menemukan
      @Repository public interface PersonRepo extends PagingAndSortingRepository<Person, Long> { //       Iterable<Person> phoneNumberContains(String number); Iterable<Person> lastName(String lastName); Iterable<Person> lastNameAndPhoneNumberContains(String lastName, String number); Iterable<Person> firstName(String firstName); Iterable<Person> firstNameAndPhoneNumberContains(String firstName, String number); Iterable<Person> firstNameAndLastName(String firstName, String lastName); Iterable<Person> firstNameAndLastNameAndPhoneNumberContains(String firstName, String lastName, String number); //  ,      default Iterable<Person> findByFirstNameAndLastNameAndPhoneNumberContains(String firstName, String lastName, String number) { if(firstName == null) { if(lastName == null) { if(number == null) { return findAll(); } else { return phoneNumberContains(number); } } else { if(number == null) { return lastName(lastName); } else { return lastNameAndPhoneNumberContains(lastName, number); } } } else { if(lastName == null) { if(number == null) { return firstName(firstName); } else { return firstNameAndPhoneNumberContains(firstName, number); } } else { if(number == null) { return firstNameAndLastName(firstName, lastName); } else { return firstNameAndLastNameAndPhoneNumberContains(firstName, lastName, number); } } } } } 



Saya tidak akan menganalisis kelebihan dan kekurangan masing-masing metode, mereka jelas. Saya hanya bisa mengatakan bahwa saya memilih opsi ketiga dengan penambahan metode pencarian untuk setiap varian kombinasi parameter dan membuat perpustakaan OpenSource yang menggunakan mekanisme Prosesor Anotasi dan pada tahap kompilasi melakukan semua pekerjaan untuk Anda. Untuk menggunakannya, Anda harus menghubungkan perpustakaan (lihat versi terbaru di https://github.com/ukman/kolobok atau https://mvnrepository.com/artifact/com.github.ukman/kolobok ).

 <dependency> <groupId>com.github.ukman</groupId> <artifactId>kolobok</artifactId> <version>0.1.2</version> <scope>compile</scope> </dependency> 

Maka Anda perlu menandai metode ini, yang seharusnya bekerja dengan cara baru dengan penjelasan @FindWithOptionalParams.

 @Repository public interface PersonRepo extends PagingAndSortingRepository<Person, Long> { @FindWithOptionalParams Iterable<Person> findByFirstNameAndLastNameAndPhoneNumberContains(String firstName, String lastName, String number); } 

Perpustakaan itu sendiri akan menghasilkan semua metode pencarian dan implementasi default dengan memeriksa parameter untuk null dan memanggil metode yang diperlukan.

PS: tulis di komentar apa penjelasan lain dapat menyederhanakan pekerjaan Anda dengan Spring, mungkin saya akan menambahkannya juga.

Source: https://habr.com/ru/post/id483796/


All Articles