Peta Tetap dengan Hibernate

1. Pengenalan

Di Hibernate, kita dapat mewakili hubungan satu-ke-banyak dalam kacang Jawa kita dengan menjadikan salah satu bidang kita menjadi Senarai .

Dalam tutorial ringkas ini, kami akan meneroka pelbagai cara untuk melakukannya dengan Peta sebagai gantinya.

2. Peta s berbeza dengan senarai s

Menggunakan Peta untuk mewakili hubungan satu-ke-banyak berbeza dari Senarai kerana kita mempunyai kunci.

Kunci ini mengubah hubungan entiti kita menjadi persatuan ternary , di mana setiap kunci merujuk kepada nilai sederhana atau objek yang boleh disisipkan atau entiti. Oleh kerana itu, untuk menggunakan Peta , kita selalu memerlukan jadual gabung untuk menyimpan kunci asing yang merujuk kepada entiti induk - kunci, dan nilainya.

Tetapi jadual gabung ini akan sedikit berbeza dengan jadual gabung yang lain kerana kunci utama tidak semestinya menjadi kunci asing kepada induk dan sasaran. Sebagai gantinya, kita akan mempunyai kunci utama sebagai gabungan kunci asing untuk ibu bapa dan lajur yang merupakan kunci Peta kita .

Pasangan nilai kunci dalam Peta mungkin terdiri daripada dua jenis: Jenis Nilai dan Jenis Entiti. Dalam bahagian berikut, kita akan melihat cara untuk mewakili persatuan ini di Hibernate.

3. Menggunakan @MapKeyColumn

Katakanlah kita mempunyai entiti Pesanan dan kita ingin memantau nama dan harga semua item dalam pesanan. Oleh itu, kami ingin memperkenalkan Peta untuk Memesan yang akan memetakan nama item dengan 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 kepada Hibernate di mana untuk mendapatkan kunci dan nilai. Untuk kuncinya, kami telah menggunakan @ MapKey Column , yang menunjukkan bahawa kunci Peta adalah ruangan item_name dari jadual bergabung kami, order_item_mapping . Begitu juga, @Column menetapkan bahawa nilai Peta sesuai dengan lajur harga jadual bergabung.

Juga, objek itemPriceMap adalah peta jenis nilai, oleh itu kita mesti menggunakan anotasi @ElementCollection .

Sebagai tambahan kepada objek jenis nilai asas, objek @ dapat disematkan juga dapat digunakan sebagai nilai Peta dengan cara yang serupa.

4. Menggunakan @MapKey

Seperti yang kita semua tahu, keperluan berubah dari masa ke masa - jadi, sekarang, katakan 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 }

Oleh itu, mari ubah Peta ke Peta di kelas entiti Pesanan :

@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 bahawa kali ini, kami akan menggunakan anotasi @MapKey sehingga Hibernate akan menggunakan Item # itemName sebagai lajur kunci peta dan bukannya memperkenalkan lajur tambahan dalam jadual bergabung. Jadi, dalam kes ini, yang menyertai meja order_item_mapping tidak mempunyai lajur utama - sebaliknya, ia merujuk kepada saya tem nama 's.

Ini berbeza dengan @MapKeyColumn. Apabila kami menggunakan @MapKeyColumn, kunci peta berada di dalam jadual bergabung . Inilah sebab mengapa kami tidak dapat menentukan pemetaan entiti kami menggunakan kedua-dua anotasi secara bersamaan.

Juga, itemMap adalah peta jenis entiti, oleh itu kita perlu menganotasi hubungan menggunakan @OneToMany atau @ManyToMany .

5. Menggunakan @MapKeyEnumerated dan @MapKeyTemporal

Setiap kali kita menentukan enum sebagai kunci Peta , kita menggunakan @MapKeyEnumerated . Begitu juga untuk nilai temporal, @MapKeyTemporal digunakan. Tingkah laku yang agak sama dengan standard @Enumerated dan @Temporal penjelasan masing-masing.

Secara lalai, ini serupa dengan @MapKeyColumn kerana lajur utama akan dibuat dalam jadual gabung. Sekiranya kita ingin menggunakan semula nilai yang sudah disimpan dalam entiti yang masih ada, kita juga harus menandakan medan dengan @MapKey .

6. Menggunakan @MapKeyJoinColumn

Seterusnya, katakan kita juga perlu memantau penjual setiap item. Salah satu cara yang mungkin kami lakukan adalah dengan menambahkan entiti Penjual dan mengikatnya dengan entiti 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 kes ini, mari kita andaikan penggunaan-kes kami adalah untuk kumpulan semua Order 's Item s oleh Penjual. Oleh itu, mari kita menukar Peta ke Peta :

@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 mencapainya kerana anotasi tersebut membolehkan Hibernate menyimpan lajur penjual_id (kunci peta) dalam urutan jadual gabungan_item_mapping bersama dengan lajur item_id . Oleh itu, pada masa membaca data dari pangkalan data, kita dapat melakukan operasi GROUP BY dengan mudah.

7. Kesimpulannya

Dalam artikel ini, kami belajar tentang beberapa cara untuk memelihara Peta di Hibernate bergantung pada pemetaan yang diperlukan.

Seperti biasa, kod sumber tutorial ini boleh didapati di Github.