noprianto
noprianto
. 9 min read

Relasi One to Many Hibernate Anotasi

Bismillah,
Artikel kali ini adalah lanjutan dari sebelumnya yang masih membahas mengenai relasi/asosiasi pada framework hibernate, yaitu one to many atau disimbolkan anotasi @OneToMany. Asosiasi ini dimana sebuah entitas dapat menerima atau meng-set informasi dari banyak instance dari entitas, sebagai contoh misalkan relasi yang terjadi antara entitas Mahasiswa dengan entitas Mata Kuliah. Misalkan ada si fulan yang mengambil matakuliah algoritma dan pemrograman, praktikum algoritma dan pemrograman, struktur data, praktikum struktur data, dan agama. Sama halnya dengan asosiasi yang sebelumnya telah kita pelajari, @OneToMany juga memiliki model Unidirectional dan BidiRectional. Beberapa penerapan @OneToMany yang dapat diterapkan menggunakan hibernate adalah sebagai berikut

@OneToMany Unidirectional {#@OneToMany-Unidirectional}

@OneToMany Unidirectional yang paling sederhana, ditampilkan seperti pada relasi tabel pada gambar di bawah ini

One to many relational unidirectional
One to many relational unidirectional

Jika kita mapping ke dalam class Java yang perlu dilakukan adalah menuliskan kode seperti ini

@Entity
@Table(name = "mahasiswa")
public class Mahasiswa implements Serializable {

    @Id
    private String nim;
    private String nama;
    private float ipk;
    private String jurusan;
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
    private List<MataKuliah> mataKuliahs = new ArrayList<MataKuliah>();

    public Mahasiswa() {
    }

    public Mahasiswa(String nim, String nama, float ipk, String jurusan) {
        this.nim = nim;
        this.nama = nama;
        this.ipk = ipk;
        this.jurusan = jurusan;
    }

//getter setter silakan digenerate menggunakan IDE

Dari potongan kode di atas setelah @OneToMany dengan property yang sebelumnya telah kita gunakan sehingga tidak perlu diperjelas kembali, ada instance mataKuliahs bertipe collection. Tujuan dari instance tersebut adalah agar instance Mahasiswa dapat menerima dan meng-set data dari entitas Alamat. Jika menggunaan model seperti ini, hibernate akan membuat tabel baru yang menyimpan informasi primary key kedua entitas. Jika pada contoh di atas tabel tersebut adalah "mahasiswa_mata_kuliah", jika kita lihat sql yang dijalankan oleh hibernate adalah sebagai berikut

Hibernate: insert into mahasiswa (ipk, jurusan, nama, nim) values (?, ?, ?, ?)
Hibernate: insert into mata_kuliah (namaMataKuliah, sks, kodeMataKuliah) values (?, ?, ?)
Hibernate: insert into mata_kuliah (namaMataKuliah, sks, kodeMataKuliah) values (?, ?, ?)
Hibernate: insert into mata_kuliah (namaMataKuliah, sks, kodeMataKuliah) values (?, ?, ?)
Hibernate: insert into mata_kuliah (namaMataKuliah, sks, kodeMataKuliah) values (?, ?, ?)
Hibernate: insert into mahasiswa_mata_kuliah (Mahasiswa_nim, mataKuliahs_kodeMataKuliah) values (?, ?)
Hibernate: insert into mahasiswa_mata_kuliah (Mahasiswa_nim, mataKuliahs_kodeMataKuliah) values (?, ?)
Hibernate: insert into mahasiswa_mata_kuliah (Mahasiswa_nim, mataKuliahs_kodeMataKuliah) values (?, ?)
Hibernate: insert into mahasiswa_mata_kuliah (Mahasiswa_nim, mataKuliahs_kodeMataKuliah) values (?, ?)

Wow, banyak sekali query insert yang dieksekusi karena ada 3 tabel yang harus diinsert data. Sepertinya model seperti ini tidak efisien, bayangnya jika datanya ada 10, 100, atau 1000? 🙁

@OneToMany Unidirectional Join Kolom {#@OneToMany-Unidirectional-Join-Kolom}

Model lain Unidirectional yang lain adalah Join kolom, anotasi yang digunakan setelah @OneToMany adalah @JoinColumn. Ketika menggunakan join kolom berarti akan ada kolom salah satu entitas menjadi foreign key pada entitas yang lain. Relasi tabel pada database relational ditunjukkan pada gambar di bawah ini

One to many relational unidirectional join column
One to many relational unidirectional join column

Mapping class Java untuk kedua entitas di atas adalah sebagai berikut

@Entity
@Table(name = "mahasiswa")
public class Mahasiswa implements Serializable {

    @Id
    private String nim;
    private String nama;
    private float ipk;
    private String jurusan;
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
    @JoinColumn(name = "nim")
    private List<MataKuliah> mataKuliahs = new ArrayList<MataKuliah>();

    public Mahasiswa() {
    }

    public Mahasiswa(String nim, String nama, float ipk, String jurusan) {
        this.nim = nim;
        this.nama = nama;
        this.ipk = ipk;
        this.jurusan = jurusan;
    }

//getter setter silakan generate menggunakan IDE

Mirip dengan deklarasi yang sebelumnya, hanya menambahkan @JoinColumn setelah @OneToMany. Ketika menggunakan model relasi jenis ini hanya akan dibuatkan 2 tabel, tetapi kolom nim akan menjadi foreign key pada entitas MataKuliah. Kemudian sql yang dijalankan ketika proses insert oleh hibernate adalah sebagai berikut

Hibernate: insert into mahasiswa (ipk, jurusan, nama, nim) values (?, ?, ?, ?)
Hibernate: insert into mata_kuliah (nama_mata_kuliah, sks, kode_mata_kuliah) values (?, ?, ?)
Hibernate: insert into mata_kuliah (nama_mata_kuliah, sks, kode_mata_kuliah) values (?, ?, ?)
Hibernate: insert into mata_kuliah (nama_mata_kuliah, sks, kode_mata_kuliah) values (?, ?, ?)
Hibernate: insert into mata_kuliah (nama_mata_kuliah, sks, kode_mata_kuliah) values (?, ?, ?)
Hibernate: update mata_kuliah set nim=? where kode_mata_kuliah=?
Hibernate: update mata_kuliah set nim=? where kode_mata_kuliah=?
Hibernate: update mata_kuliah set nim=? where kode_mata_kuliah=?
Hibernate: update mata_kuliah set nim=? where kode_mata_kuliah=?

Ternyata query yang dijalankan masih belum efisen, perbedaaannya terdapat query update ketika hibernate menjalankan method save().

@OneToMany Unidirectional Join Tabel {#@OneToMany-Unidirectional-Join-Tabel}

Sama seperti yang model yang pertama sebenarnya, perbedaannya adalah ketika menggunakan model jenis ini nama tabel dan kolom-kolomnya yang menghubungkan kedua entitas dapat diberi nama sesuai yang kita inginkan. Anotasi yang digunakan setelah @OneToMany menggunakan @JoinTable, mapping class Java dapat dicontohkan seperti berikut ini

@Entity
@Table(name = "mahasiswa")
public class Mahasiswa implements Serializable {

    @Id
    private String nim;
    private String nama;
    private float ipk;
    private String jurusan;
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
    @JoinTable(name = "mhs_mk", joinColumns = @JoinColumn(name = "nim"), inverseJoinColumns = @JoinColumn(name = "kode_mk"))
    private List<MataKuliah> mataKuliahs = new ArrayList<MataKuliah>();

    public Mahasiswa() {
    }

    public Mahasiswa(String nim, String nama, float ipk, String jurusan) {
        this.nim = nim;
        this.nama = nama;
        this.ipk = ipk;
        this.jurusan = jurusan;
    }

Dari kode di atas terdapat baris @JoinTable(name = "mhs_mk", joinColumns = @JoinColumn(name = "nim"), inverseJoinColumns = @JoinColumn(name = "kode_mk")) maksudnya adalah akan membuat sebuah tabel dengan nama "mhs_mk" dengan kolom "nim" dan kolom "kode_mk".

@OneToMany Bidirectional {#@OneToMany-Bidirectional}

Model jenis ini merupakan relasi yang paling efisien untuk dapat digunakan pada aplikasi yang akan Anda bangun, jika pada ERD seperti di bawah ini

One to many relational bidirectional
One to many relational bidirectional

Gambar ERD di atas memang mirip dengan anotasi menggunakan @OneToMany Unidirectional join kolom, perbedaaanya adalah pada class Java mappingnya. Mapping tersebut dapat dilihat pada potongan kode di bawah ini

@Entity
@Table(name = "mahasiswa")
public class Mahasiswa implements Serializable {

    @Id
    private String nim;
    private String nama;
    private float ipk;
    private String jurusan;
    @OneToMany(mappedBy = "mahasiswa", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<MataKuliah> mataKuliahs = new ArrayList<MataKuliah>();

    public Mahasiswa() {
    }

    public Mahasiswa(String nim, String nama, float ipk, String jurusan) {
        this.nim = nim;
        this.nama = nama;
        this.ipk = ipk;
        this.jurusan = jurusan;
    }

//getter setter silakan digenerate menggunakan IDE

Dengan menambahakan property mappedBy = "mahasiswa" pada @OneToMany berfungsi untuk memapping instance mahasiswa ke dalam entitas MataKuliah, selanjutnya untuk entitas MataKuliah java class mapping adalah sebagai berikut

@Entity
@Table(name = "mata_kuliah")
public class MataKuliah implements Serializable {

    @Id
    @Column(name = "kode_mata_kuliah")
    private String kodeMataKuliah;
    @Column(name = "nama_mata_kuliah")
    private String namaMataKuliah;
    private short sks;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "nim")
    private Mahasiswa mahasiswa;

    public MataKuliah() {
    }

    public MataKuliah(String kodeMataKuliah, String namaMataKuliah, short sks) {
        this.kodeMataKuliah = kodeMataKuliah;
        this.namaMataKuliah = namaMataKuliah;
        this.sks = sks;
    }

//Silakan getter dan setter digenerated menggunakan IDE

Berbeda dari yang sebelumnya pada entitas MataKuliah ditambahkan @ManyToOne(fetch = FetchType.LAZY) atau kebalikan dari relasi @OneToMany pada entitas Mahasiswa, fetch = FetchType.LAZY bertujuan agar ketika instance Mahasiswa load data tidak semua data yang terdapat pada entitas MataKuliah tidak terload. Sementara untuk query yang dijalankan oleh hibernate adalah sebagai berikut

Hibernate: insert into mahasiswa (ipk, jurusan, nama, nim) values (?, ?, ?, ?)
Hibernate: insert into mata_kuliah (nim, nama_mata_kuliah, sks, kode_mata_kuliah) values (?, ?, ?, ?)
Hibernate: insert into mata_kuliah (nim, nama_mata_kuliah, sks, kode_mata_kuliah) values (?, ?, ?, ?)
Hibernate: insert into mata_kuliah (nim, nama_mata_kuliah, sks, kode_mata_kuliah) values (?, ?, ?, ?)
Hibernate: insert into mata_kuliah (nim, nama_mata_kuliah, sks, kode_mata_kuliah) values (?, ?, ?, ?)

Terlihat dari output ketika method save() dijalankan, querynya lebih sederhana dibanding dengan @OneToManyyang sebelumnya. Untuk kode di atas dapat didapatkan di sini.

Demikian tulisan saya tentang relasi one to many menggunakan hibernate, semoga bermanfaat dan menjadi ilmu yang baru untuk temen-temen yang baru belajar hibernate seperti saya. Saran dan kritik senantiasa dinantikan untuk memperbaiki kekurangan tulisan pada blog ini. ^_^

comments powered by Disqus