Repositori Kompos Data Spring

1. Pengenalan

Semasa memodelkan sistem atau proses dunia nyata, repositori gaya reka bentuk berdasarkan domain (DDD) adalah pilihan yang baik. Untuk tujuan ini, kami dapat menggunakan Spring Data JPA sebagai lapisan abstraksi akses data kami.

Sekiranya anda baru dalam konsep ini, lihat tutorial pengenalan ini untuk membantu anda mencapai tahap yang pantas.

Dalam tutorial ini, kita akan memfokuskan pada konsep membuat repositori khusus dan komposit yang dibuat menggunakan repositori yang lebih kecil yang disebut fragmen.

2. Pergantungan Maven

Pilihan untuk membuat repositori komposit tersedia bermula pada Spring 5.

Mari tambahkan kebergantungan yang diperlukan untuk Spring Data JPA:

 org.springframework.data spring-data-jpa 2.2.2.RELEASE 

Kami juga perlu menyediakan sumber data agar lapisan akses data kami berfungsi. Sebaiknya sediakan pangkalan data dalam memori seperti H2 untuk pengembangan dan ujian pantas.

3. Latar belakang

3.1. Hibernate sebagai Pelaksanaan JPA

JPA Data Spring, secara lalai, menggunakan Hibernate sebagai pelaksanaan JPA. Kita boleh mengelirukan satu dengan yang lain atau membandingkannya dengan mudah tetapi mereka mempunyai tujuan yang berbeza.

Spring Data JPA adalah lapisan abstraksi akses data di bawah di mana kita dapat menggunakan pelaksanaan apa pun. Sebagai contoh, kita dapat menukar Hibernate untuk memilih EclipseLink.

3.2. Repositori Lalai

Dalam banyak kes, kita sendiri tidak perlu menulis sebarang pertanyaan.

Sebagai gantinya, kita hanya perlu membuat antara muka yang seterusnya memperluas antara muka repositori data Spring umum:

public interface LocationRepository extends JpaRepository { }

Dan ini, dengan sendirinya, membolehkan kita melakukan operasi biasa - CRUD, paging, dan sorting - pada objek Lokasi yang mempunyai kunci utama jenis Long .

Selanjutnya, Spring Data JPA dilengkapi dengan mekanisme pembangun pertanyaan yang menyediakan keupayaan untuk menghasilkan pertanyaan bagi pihak kami menggunakan konvensyen nama kaedah:

public interface StoreRepository extends JpaRepository { List findStoreByLocationId(Long locationId); }

3.3. Repositori Tersuai

Sekiranya diperlukan, kami dapat memperkayakan repositori model kami dengan menulis antara muka fragmen dan melaksanakan fungsi yang diinginkan. Ini kemudian boleh disuntikkan di repositori JPA kita sendiri.

Sebagai contoh, di sini kita memperkayakan ItemTypeRepository kami dengan memperluas repositori fragmen:

public interface ItemTypeRepository extends JpaRepository, CustomItemTypeRepository { }

Di sini CustomItemTypeRepository adalah antara muka lain:

public interface CustomItemTypeRepository { void deleteCustomById(ItemType entity); }

Pelaksanaannya dapat menjadi repositori dalam bentuk apa pun, bukan hanya JPA:

public class CustomItemTypeRepositoryImpl implements CustomItemTypeRepository { @Autowired private EntityManager entityManager; @Override public void deleteCustomById(ItemType itemType) { entityManager.remove(itemType); } }

Kita hanya perlu memastikan bahawa ia mempunyai Impl postfix . Namun, kami dapat menetapkan postfix tersuai dengan menggunakan konfigurasi XML berikut:

atau dengan menggunakan penjelasan ini:

@EnableJpaRepositories( basePackages = "com.baeldung.repository", repositoryImplementationPostfix = "CustomImpl")

4. Menyusun Repositori Menggunakan Pelbagai Fragmen

Sehingga beberapa rilis yang lalu, kami hanya dapat memperluas antarmuka repositori kami menggunakan satu implementasi khusus. Ini adalah batasan kerana kami harus memasukkan semua fungsi yang berkaitan ke dalam satu objek.

Tidak perlu dikatakan, untuk projek yang lebih besar dengan model domain kompleks, ini membawa kepada kelas kembung.

Sekarang dengan Spring 5, kami mempunyai pilihan untuk memperkayakan repositori JPA kami dengan beberapa repositori fragmen . Sekali lagi, syaratnya tetap ada bahawa kita mempunyai serpihan ini sebagai pasangan antara muka-pelaksanaan.

Untuk menunjukkan ini, mari kita buat dua serpihan:

public interface CustomItemTypeRepository { void deleteCustom(ItemType entity); void findThenDelete(Long id); } public interface CustomItemRepository { Item findItemById(Long id); void deleteCustom(Item entity); void findThenDelete(Long id); }

Sudah tentu, kita perlu menulis pelaksanaannya. Tetapi bukannya memasang repositori tersuai ini - dengan fungsi yang berkaitan - di repositori JPA mereka sendiri, kami dapat memperluas fungsi repositori JPA tunggal:

public interface ItemTypeRepository extends JpaRepository, CustomItemTypeRepository, CustomItemRepository { }

Sekarang, kita mempunyai semua fungsi yang dipautkan dalam satu repositori tunggal.

5. Berurusan dengan Kekaburan

Oleh kerana kami mewarisi dari beberapa repositori, kami mungkin menghadapi masalah untuk mengetahui pelaksanaan mana yang akan digunakan sekiranya terjadi bentrokan. Sebagai contoh, dalam contoh kami, kedua-dua repositori fragmen mempunyai kaedah, findThenDelete () , dengan tandatangan yang sama.

Dalam senario ini, urutan deklarasi antara muka digunakan untuk menyelesaikan kesamaran . Oleh itu, dalam kes kami, kaedah di dalam CustomItemTypeRepository akan digunakan sejak dinyatakan pertama.

Kami boleh mengujinya dengan menggunakan kes ujian ini:

@Test public void givenItemAndItemTypeWhenDeleteThenItemTypeDeleted() { Optional itemType = composedRepository.findById(1L); assertTrue(itemType.isPresent()); Item item = composedRepository.findItemById(2L); assertNotNull(item); composedRepository.findThenDelete(1L); Optional sameItemType = composedRepository.findById(1L); assertFalse(sameItemType.isPresent()); Item sameItem = composedRepository.findItemById(2L); assertNotNull(sameItem); }

6. Kesimpulannya

Dalam artikel ini, kami melihat pelbagai cara di mana kami dapat menggunakan repositori Spring Data JPA. Kami melihat bahawa Spring menjadikannya mudah untuk melakukan operasi pangkalan data pada objek domain kami tanpa menulis banyak kod atau bahkan pertanyaan SQL.

Sokongan ini dapat disesuaikan dengan penggunaan repositori komposit.

Coretan kod dari artikel ini boleh didapati sebagai projek Maven di GitHub.