Repositori Komposit Data Musim Semi

1. Perkenalan

Saat memodelkan sistem atau proses dunia nyata, repositori gaya desain berbasis domain (DDD) adalah pilihan yang baik. Untuk tujuan ini, kita dapat menggunakan Spring Data JPA sebagai lapisan abstraksi akses data kita.

Jika Anda baru mengenal konsep ini, lihat tutorial pengantar ini untuk membantu Anda mempercepat.

Dalam tutorial ini, kita akan fokus pada konsep membuat repositori ubahsuaian serta yang dapat disusun yang dibuat menggunakan repositori lebih kecil yang disebut fragmen.

2. Ketergantungan Maven

Opsi untuk membuat repositori yang dapat disusun tersedia mulai dengan Spring 5.

Mari tambahkan dependensi yang diperlukan untuk Spring Data JPA:

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

Kami juga perlu menyiapkan sumber data agar lapisan akses data kami berfungsi. Sebaiknya siapkan database dalam memori seperti H2 untuk pengembangan dan pengujian cepat.

3. Latar Belakang

3.1. Hibernate sebagai Implementasi JPA

Spring Data JPA, secara default, menggunakan Hibernate sebagai implementasi JPA. Kita dapat dengan mudah membingungkan satu sama lain atau membandingkannya tetapi keduanya memiliki tujuan yang berbeda.

Spring Data JPA adalah lapisan abstraksi akses data di bawah ini yang dapat kita gunakan untuk implementasi apa pun. Kami dapat, misalnya, mengganti mode Hibernate menjadi EclipseLink.

3.2. Repositori Default

Dalam banyak kasus, kami tidak perlu menulis kueri apa pun sendiri.

Sebagai gantinya, kita hanya perlu membuat antarmuka yang pada gilirannya memperluas antarmuka repositori data Spring generik:

public interface LocationRepository extends JpaRepository { }

Dan ini, dengan sendirinya, akan memungkinkan kita melakukan operasi umum - CRUD, paging, dan pengurutan - pada objek Lokasi yang memiliki kunci utama berjenis Long .

Selain itu, Spring Data JPA dilengkapi dengan mekanisme pembuat kueri yang memberikan kemampuan untuk menghasilkan kueri atas nama kami menggunakan konvensi nama metode:

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

3.3. Repositori Kustom

Jika diperlukan, kita bisa memperkaya repositori model kita dengan menulis antarmuka fragmen dan mengimplementasikan fungsionalitas yang diinginkan. Ini kemudian dapat dimasukkan ke dalam repositori JPA kita sendiri.

Misalnya, di sini kami memperkaya ItemTypeRepository kami dengan memperluas repositori fragmen:

public interface ItemTypeRepository extends JpaRepository, CustomItemTypeRepository { }

Di sini CustomItemTypeRepository adalah antarmuka lain:

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

Implementasinya dapat berupa repositori apa pun, bukan hanya JPA:

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

Kami hanya perlu memastikan bahwa ia memiliki postfix Impl . Namun, kita dapat menyetel postfix kustom dengan menggunakan konfigurasi XML berikut ini:

atau dengan menggunakan anotasi ini:

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

4. Membuat Repositori Menggunakan Banyak Fragmen

Hingga beberapa rilis yang lalu, kami hanya dapat memperluas antarmuka repositori kami menggunakan satu implementasi kustom. Ini adalah batasan karena kami harus membawa semua fungsionalitas terkait ke dalam satu objek.

Tak perlu dikatakan, untuk proyek yang lebih besar dengan model domain yang kompleks, ini menyebabkan kelas membengkak.

Sekarang dengan Spring 5, kami memiliki opsi untuk memperkaya repositori JPA kami dengan beberapa repositori fragmen . Sekali lagi, persyaratannya tetap bahwa kita memiliki fragmen ini sebagai pasangan implementasi antarmuka.

Untuk mendemonstrasikan ini, mari buat dua fragmen:

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); }

Tentu saja, kami perlu menulis implementasinya. Tetapi alih-alih memasukkan repositori khusus ini - dengan fungsi terkait - di repositori JPA mereka sendiri, kami dapat memperluas fungsionalitas dari satu repositori JPA:

public interface ItemTypeRepository extends JpaRepository, CustomItemTypeRepository, CustomItemRepository { }

Sekarang, kita akan memiliki semua fungsionalitas yang ditautkan dalam satu repositori.

5. Berurusan dengan Ambiguitas

Karena kami mewarisi dari beberapa repositori, kami mungkin mengalami masalah dalam menentukan implementasi mana yang akan digunakan jika terjadi bentrokan. Misalnya, dalam contoh kita, kedua repositori fragmen memiliki metode, findThenDelete () , dengan tanda tangan yang sama.

Dalam skenario ini, urutan deklarasi antarmuka digunakan untuk menyelesaikan ambiguitas . Akibatnya, dalam kasus kami, metode di dalam CustomItemTypeRepository akan digunakan sejak dideklarasikan terlebih dahulu.

Kami dapat menguji ini dengan menggunakan kasus uji 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. Kesimpulan

Pada artikel ini, kami melihat berbagai cara yang dapat kami gunakan untuk menggunakan repositori JPA Spring Data. Kami melihat bahwa Spring memudahkan untuk melakukan operasi database pada objek domain kami tanpa menulis banyak kode atau bahkan kueri SQL.

Dukungan ini sangat dapat disesuaikan melalui penggunaan repositori yang dapat disusun.

Potongan kode dari artikel ini tersedia sebagai proyek Maven di sini di GitHub.