Pernahkah Anda merasa kebingungan ketika harus mengelola relasi kompleks antar entitas dalam aplikasi Anda? Terutama saat menghadapi situasi di mana satu entitas dapat berhubungan dengan banyak entitas lainnya dan sebaliknya, seperti pada relasi antara Artikel dan Penulis Blog. Kebingungan ini dapat menghambat alur kerja dan menyebabkan kode menjadi tidak efisien serta sulit dipelihara. Tapi jangan khawatir, dalam artikel ini, kami akan membahas secara rinci tentang bagaimana mengimplementasikan relasi many-to-many menggunakan Spring Boot dan Hibernate. Dengan panduan ini, Anda akan mampu menangani relasi antar entitas dengan lebih mudah dan efektif.
ERD
kita bisa gambarkan dulu ERD antara Artikel (ARTIKEL) dan Penulis Blog (PENULIS_BLOG). Digunakan tabel pivot KONTEN untuk menghubungkan dua entitas ini, seperti pada gambar di bawah. Tabel konten kemudian menyimpan id dari masing-masing tabel.
Model
Artikel
@Entity
@Data
public class Artikel {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String judul;
private String kategori;
@ManyToMany(mappedBy = "artikels")
@ToString.Exclude
@EqualsAndHashCode.Exclude
private Set<PenulisBlog> penulisSet = new HashSet<>();
}
PenulisBlog
@Entity
@Data
public class PenulisBlog {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String nama;
@ManyToMany
@JoinTable(
name = "konten",
joinColumns = @JoinColumn(name = "id_penulis"),
inverseJoinColumns = @JoinColumn(name = "id_artikel")
)
@ToString.Exclude
@EqualsAndHashCode.Exclude
private Set<Artikel> artikels = new HashSet<Artikel>();
}
Jika dilihat pada Model Artikel, khususnya pada bagian private Set<Artikel> artikels = new HashSet<Artikel>();. Terdapat beberapa banyak anotasi, dengan penjelasannya sebagai berikut :
- @ManyToMany: Anotasi ini menunjukkan bahwa properti artikels memiliki relasi many-to-many dengan model Artikel. Dalam relasi many-to-many, setiap entitas PenulisBlog bisa terkait dengan banyak entitas Artikel, dan sebaliknya, setiap entitas Artikel bisa terkait dengan banyak model PenulisBlog.
- @JoinTable:Anotasi ini digunakan untuk menentukan tabel join (tabel pivot) yang akan digunakan untuk menyimpan relasi many-to-many di basis data. Dalam hal ini, tabel join diberi nama konten.
- name = "konten": Menentukan nama tabel join (pivot) dengan nama tabelnya adalah konten.
- joinColumns = @JoinColumn(name = "id_penulis"): Menentukan kolom dalam tabel join yang berfungsi sebagai foreign key untuk model PenulisBlog. Kolom ini dinamai id_penulis.
- inverseJoinColumns = @JoinColumn(name = "id_artikel"): Menentukan kolom dalam tabel join yang berfungsi sebagai foreign key untuk entitas Artikel. Kolom ini dinamai id_artikel.
- @ToString.Exclude: Anotasi ini berasal dari project Lombok dan digunakan untuk mengecualikan (exclude) properti artikels dari metode toString yang dihasilkan secara otomatis. Berguna untuk menghindari infinite loop rekursif yang dapat terjadi jika properti ini termasuk dalam toString.
- @EqualsAndHashCode.Exclude: Anotasi ini juga berasal dari project Lombok dan digunakan untuk mengecualikan properti artikels dari metode equals dan hashCode yang dihasilkan secara otomatis. Ini berguna untuk menghindari masalah infinite loop rekursif dan mempertahankan kinerja metode equals dan hashCode.
- private Set<Artikel> artikels = new HashSet<Artikel>();: Mendefinisikan properti artikels sebagai sebuah Set yang berisi objek-objek Artikel. HashSet digunakan untuk menginisialisasi artikels dengan sebuah instance dari HashSet. Ini memastikan bahwa properti ini tidak bernilai null ketika objek PenulisBlogbaru dibuat.
Repositoy
ArtikelRepositoy
@Repository
public interface ArtikelRepository extends JpaRepository<Artikel, Long>{
}
PenulisBlogRepositoy
@Repository
public interface PenulisBlogRepository extends JpaRepository<PenulisBlog, Long>{
}
Service
BlogService
@Service
@Data
public class BlogService {
private final ArtikelRepository artikelRepository;
private final PenulisBlogRepository penulisBlogRepository;
@Transactional(propagation = Propagation.REQUIRED)
public Artikel storeArtikel(Artikel artikel) {
artikelRepository.save(artikel);
return artikel;
}
@Transactional(propagation = Propagation.REQUIRED)
public PenulisBlog storePenulisBlog(PenulisBlog penulisBlog) {
penulisBlogRepository.save(penulisBlog);
return penulisBlog;
}
@Transactional(propagation = Propagation.REQUIRED)
public Artikel addPenulisBlogToArtikel(Long artikelId, Long blogId) {
Artikel artikel = artikelRepository.findById(artikelId)
.orElseThrow(() -> new RuntimeException("artikel with id " +artikelId + " not found"));
PenulisBlog penulisBlog = penulisBlogRepository.findById(blogId)
.orElseThrow(() -> new RuntimeException("Penulis Blog with id " +artikelId + " not found"));
artikel.getPenulisSet().add(penulisBlog);
penulisBlog.getArtikels().add(artikel);
artikelRepository.save(artikel);
penulisBlogRepository.save(penulisBlog);
return artikel;
}
}
Pada service BlogService, terdapat 3 fungsi yaitu service untuk save Artikel (storeArtikel), save PenulisBlog (storePenulisBlog), dan Melakukan relasi antara Artikel dan PenulisBlog (addPenulisBlogToArtikel). Pada addPenulisBlogToArtikel terlihat melakukan bidirectional antara 2 object yaitu Set PenulisBlog pada object artikel ditambahkan object penulisBlog begitu pula sebaliknya.
Metode addPenulisBlogToArtikel bertugas untuk menambahkan relasi many-to-many antara Artikel dan PenulisBlog. Metode ini pertama-tama mencari Artikel dan PenulisBlog berdasarkan ID dua tabel-tabel masing, dan jika tidak ditemukan, akan melempar RuntimeException. Setelah menemukan kedua entitas, metode ini menambahkan PenulisBlog ke dalam koleksi penulisBlogs di Artikel dan menambahkan Artikel ke dalam koleksi artikels di PenulisBlog. Kedua entitas tersebut kemudian disimpan kembali ke dalam basis data, memastikan bahwa perubahan tersebut konsisten dan berjalan dalam satu transaksi.
Code Test & Hasil
Code Test
public static void runBlog(BlogService blogService) {
//add Penulis Blog
PenulisBlog radit = new PenulisBlog();
radit.setNama("Raditya Dika");
radit = blogService.storePenulisBlog(radit);
//add Artikel
Artikel artikel = new Artikel();
artikel.setJudul("Kambing Jantan dalam Blog");
artikel.setKategori("Komedi");
artikel = blogService.storeArtikel(artikel);
//connect
artikel = blogService.addPenulisBlogToArtikel(artikel.getId(), radit.getId());
}
Hasil
Untuk akses full code bisa dilihat pada github berikut.
Sekian dari saya, mohon maaf atas kekurangan dan terimakasih sudah membaca. Semoga membantu, jangan lupa untuk berkomentar.
Referensi
- https://www.baeldung.com/jpa-many-to-many diakses 14 Juli 2024
- https://www.geeksforgeeks.org/jpa-many-to-many-mapping/ diakses 14 Juli 2024
Posting Komentar untuk "Spring boot Hibernate Basic 6 Memahami Relasi Many-to-Many Spring Boot JPA"
Berilah komentar, saran, dan kritik dengan bijak