Peta Tetap dengan Hibernate

1. Perkenalan

Dalam Hibernate, kita dapat merepresentasikan hubungan satu-ke-banyak dalam kacang Java kita dengan membuat salah satu bidang kita menjadi Daftar .

Dalam tutorial singkat ini, kita akan menjelajahi berbagai cara untuk melakukan ini dengan Peta .

2. Peta s Berbeda dari Daftar s

Menggunakan Peta untuk merepresentasikan hubungan satu-ke-banyak berbeda dari Daftar karena kita memiliki kunci.

Kunci ini mengubah relasi entitas kita menjadi asosiasi ternary , di mana setiap kunci merujuk ke nilai sederhana atau objek yang dapat disematkan atau entitas. Karena itu, untuk menggunakan Peta , kita akan selalu membutuhkan tabel gabungan untuk menyimpan kunci asing yang mereferensikan entitas induk - kunci, dan nilainya.

Tetapi tabel gabungan ini akan sedikit berbeda dari tabel gabungan lainnya karena kunci utama tidak harus berupa kunci asing bagi induk dan target. Sebagai gantinya, kita akan membuat kunci utama menjadi gabungan dari kunci asing ke induk dan kolom yang merupakan kunci untuk Peta kita .

Pasangan nilai-kunci di Peta mungkin terdiri dari dua jenis: Jenis Nilai dan Jenis Entitas. Pada bagian berikut, kita akan melihat cara untuk merepresentasikan asosiasi ini dalam Hibernate.

3. Menggunakan @MapKeyColumn

Katakanlah kita memiliki entitas Order dan kita ingin melacak nama dan harga semua item dalam sebuah pesanan. Jadi, kami ingin memperkenalkan Map to Order yang akan memetakan nama item ke harganya:

@Entity @Table(name = "orders") public class Order { @Id @GeneratedValue @Column(name = "id") private int id; @ElementCollection @CollectionTable(name = "order_item_mapping", joinColumns = {@JoinColumn(name = "order_id", referencedColumnName = "id")}) @MapKeyColumn(name = "item_name") @Column(name = "price") private Map itemPriceMap; // standard getters and setters }

Kita perlu menunjukkan ke Hibernate di mana mendapatkan kunci dan nilainya. Untuk kunci, kami telah menggunakan @ MapKey Kolom , menunjukkan bahwa Peta kunci 's adalah ITEM_NAME kolom meja kami bergabung, order_item_mapping . Demikian pula, @Column menentukan bahwa nilai Map sesuai dengan kolom harga dari tabel gabungan.

Selain itu, objek itemPriceMap adalah peta tipe nilai, jadi kita harus menggunakan anotasi @ElementCollection .

Selain objek tipe nilai dasar, objek @ Embeddable juga dapat digunakan sebagai nilai Peta dengan cara yang sama.

4. Menggunakan @MapKey

Seperti yang kita semua tahu, persyaratan berubah seiring waktu - jadi, sekarang, katakanlah kita perlu menyimpan beberapa atribut Item bersama dengan itemName dan itemPrice :

@Entity @Table(name = "item") public class Item { @Id @GeneratedValue @Column(name = "id") private int id; @Column(name = "name") private String itemName; @Column(name = "price") private double itemPrice; @Column(name = "item_type") @Enumerated(EnumType.STRING) private ItemType itemType; @Temporal(TemporalType.TIMESTAMP) @Column(name = "created_on") private Date createdOn; // standard getters and setters }

Karenanya, mari kita ubah Map menjadi Map di kelas entitas Order :

@Entity @Table(name = "orders") public class Order { @Id @GeneratedValue @Column(name = "id") private int id; @OneToMany(cascade = CascadeType.ALL) @JoinTable(name = "order_item_mapping", joinColumns = {@JoinColumn(name = "order_id", referencedColumnName = "id")}, inverseJoinColumns = {@JoinColumn(name = "item_id", referencedColumnName = "id")}) @MapKey(name = "itemName") private Map itemMap; }

Perhatikan bahwa kali ini, kita akan menggunakan anotasi @MapKey sehingga Hibernate akan menggunakan Item # itemName sebagai kolom kunci peta alih-alih memasukkan kolom tambahan di tabel gabungan. Jadi, dalam hal ini, join table order_item_mapping tidak memiliki kolom kunci - bukan, itu mengacu pada saya tem nama 's.

Ini berbeda dengan @MapKeyColumn. Saat kita menggunakan @MapKeyColumn, kunci peta berada di tabel gabungan . Inilah alasan mengapa kami tidak dapat menentukan pemetaan entitas kami menggunakan kedua anotasi dalam hubungannya.

Juga, itemMap adalah peta entitas jenis, oleh karena itu kita harus membubuhi keterangan hubungan menggunakan @OneToMany atau @ManyToMany .

5. Menggunakan @MapKeyEnumerated dan @MapKeyTemporal

Setiap kali kami menetapkan enum sebagai kunci Peta , kami menggunakan @MapKeyEnumerated . Demikian pula, untuk nilai temporal, @MapKeyTemporal digunakan. Perilakunya sangat mirip dengan anotasi @Enumerated dan @Temporal standar .

Secara default, ini mirip dengan @MapKeyColumn di mana kolom kunci akan dibuat di tabel gabungan. Jika kita ingin menggunakan kembali nilai yang sudah disimpan dalam entitas yang ada, kita juga harus menandai bidang tersebut dengan @MapKey .

6. Menggunakan @MapKeyJoinColumn

Selanjutnya, katakanlah kita juga perlu melacak penjual setiap barang. Salah satu cara kami dapat melakukan ini adalah dengan menambahkan entitas Penjual dan mengikatnya ke entitas Item kami :

@Entity @Table(name = "seller") public class Seller { @Id @GeneratedValue @Column(name = "id") private int id; @Column(name = "name") private String sellerName; // standard getters and setters }
@Entity @Table(name = "item") public class Item { @Id @GeneratedValue @Column(name = "id") private int id; @Column(name = "name") private String itemName; @Column(name = "price") private double itemPrice; @Column(name = "item_type") @Enumerated(EnumType.STRING) private ItemType itemType; @Temporal(TemporalType.TIMESTAMP) @Column(name = "created_on") private Date createdOn; @ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name = "seller_id") private Seller seller; // standard getters and setters }

Dalam hal ini, mari kita asumsikan penggunaan-kasus kami adalah untuk mengelompokkan semua Orde 's Barang s oleh Penjual. Karenanya, mari kita ubah Map menjadi Map :

@Entity @Table(name = "orders") public class Order { @Id @GeneratedValue @Column(name = "id") private int id; @OneToMany(cascade = CascadeType.ALL) @JoinTable(name = "order_item_mapping", joinColumns = {@JoinColumn(name = "order_id", referencedColumnName = "id")}, inverseJoinColumns = {@JoinColumn(name = "item_id", referencedColumnName = "id")}) @MapKeyJoinColumn(name = "seller_id") private Map sellerItemMap; // standard getters and setters }

Kita perlu menambahkan @MapKeyJoinColumn untuk mencapai ini karena anotasi itu memungkinkan Hibernate untuk menyimpan kolom seller_id (kunci peta) di tabel gabungan order_item_mapping bersama dengan kolom item_id . Jadi, pada saat membaca data dari database, kita dapat melakukan operasi GROUP BY dengan mudah.

7. Kesimpulan

Dalam artikel ini, kami belajar tentang beberapa cara untuk mempertahankan Peta dalam Hibernasi tergantung pada pemetaan yang diperlukan.

Seperti biasa, kode sumber dari tutorial ini dapat ditemukan di Github.