Apa perbedaan antara asosiasi Searah dan Dua Arah?
Karena tabel yang dihasilkan di db semuanya sama, jadi satu-satunya perbedaan yang saya temukan adalah bahwa setiap sisi dari asosiasi dua arah akan merujuk ke yang lain, dan tidak searah.
Ini adalah asosiasi Searah
public class User {
private int id;
private String name;
@ManyToOne
@JoinColumn(
name = "groupId")
private Group group;
}
public class Group {
private int id;
private String name;
}
Asosiasi dua arah
public class User {
private int id;
private String name;
@ManyToOne
@JoinColumn(
name = "groupId")
private Group group;
}
public class Group {
private int id;
private String name;
@OneToMany(mappedBy="group")
private List<User> users;
}
Perbedaannya adalah apakah grup tersebut memiliki referensi pengguna.
Jadi saya bertanya-tanya apakah ini satu-satunya perbedaan? mana yang direkomendasikan?
Jawaban:
Perbedaan utamanya adalah bahwa hubungan dua arah menyediakan akses navigasi di kedua arah, sehingga Anda dapat mengakses sisi lain tanpa kueri eksplisit. Juga memungkinkan Anda untuk menerapkan opsi berjenjang ke kedua arah.
Perhatikan bahwa akses navigasi tidak selalu bagus, terutama untuk hubungan "satu-ke-sangat-banyak" dan "banyak-ke-sangat-banyak". Bayangkan sebuah
Group
yang berisi ribuanUser
s:Bagaimana Anda mengaksesnya? Dengan begitu banyak
User
, Anda biasanya perlu menerapkan beberapa pemfilteran dan / atau penomoran halaman, sehingga Anda tetap perlu menjalankan kueri (kecuali Anda menggunakan pemfilteran koleksi , yang menurut saya tampak seperti retasan). Beberapa pengembang mungkin cenderung menerapkan pemfilteran dalam memori dalam kasus seperti itu, yang jelas tidak baik untuk kinerja. Perhatikan bahwa memiliki hubungan seperti itu dapat mendorong pengembang semacam ini untuk menggunakannya tanpa mempertimbangkan implikasi kinerja.Bagaimana Anda menambahkan
User
s baru keGroup
? Untungnya, Hibernate melihat sisi hubungan pemilik saat mempertahankannya, jadi Anda hanya dapat menyetelnyaUser.group
. Namun, jika Anda ingin menyimpan obyek dalam memori konsisten, Anda juga perlu menambahkanUser
untukGroup.users
. Tapi itu akan membuat Hibernate mengambil semua elemen dariGroup.users
database!Jadi, saya tidak setuju dengan rekomendasi dari Praktik Terbaik . Anda perlu merancang hubungan dua arah dengan hati-hati, dengan mempertimbangkan kasus penggunaan (apakah Anda memerlukan akses navigasi di kedua arah?) Dan kemungkinan implikasi kinerja.
Lihat juga:
sumber
setGroup()
dariaddUser()
untuk menjaga kedua sisi konsisten.setGroup()
tanpaaddUser()
, tetapi itu akan menghasilkan status objek dalam memori yang tidak konsisten.Ada dua perbedaan utama.
Mengakses sisi asosiasi
Yang pertama terkait dengan bagaimana Anda akan mengakses hubungan tersebut. Untuk pengaitan searah, Anda dapat menavigasi pengaitan dari satu ujung saja.
Jadi, untuk
@ManyToOne
asosiasi searah , itu berarti Anda hanya dapat mengakses hubungan dari sisi anak tempat kunci asing berada.Jika Anda memiliki
@OneToMany
asosiasi searah , itu berarti Anda hanya dapat mengakses hubungan dari sisi induk yang mengelola kunci asing.Untuk
@OneToMany
pengaitan dua arah , Anda dapat menavigasi pengaitan dengan kedua cara, baik dari sisi induk atau dari sisi anak.Anda juga perlu menggunakan metode tambah / hapus utilitas untuk asosiasi dua arah untuk memastikan bahwa kedua sisi disinkronkan dengan benar .
Performa
Aspek kedua terkait dengan kinerja.
@OneToMany
, asosiasi searah tidak berkinerja sebaik asosiasi dua arah .@OneToOne
, asosiasi dua arah akan menyebabkan induk diambil dengan penuh semangat jika Hibernasi tidak dapat membedakan apakah Proxy harus ditetapkan atau nilai null .@ManyToMany
, jenis koleksi membuat perbedaan cukup besar karenaSets
kinerjanya lebih baik daripadaLists
.sumber
from the child side where the foreign key resides.
from the parent side where the foreign key resides.
Dalam hal pengkodean, hubungan dua arah lebih kompleks untuk diterapkan karena aplikasi bertanggung jawab untuk menjaga kedua sisi selaras sesuai dengan spesifikasi JPA 5 (pada halaman 42). Sayangnya contoh yang diberikan dalam spesifikasi tidak memberikan detail lebih lanjut, sehingga tidak memberikan gambaran tingkat kerumitannya.
Saat tidak menggunakan cache tingkat kedua, biasanya bukan masalah jika metode hubungan tidak diimplementasikan dengan benar karena instance akan dibuang di akhir transaksi.
Saat menggunakan cache tingkat kedua, jika ada yang rusak karena metode penanganan hubungan yang diterapkan secara salah, ini berarti bahwa transaksi lain juga akan melihat elemen yang rusak (cache tingkat kedua bersifat global).
Hubungan dua arah yang diterapkan dengan benar dapat membuat kueri dan kode lebih sederhana, tetapi tidak boleh digunakan jika tidak masuk akal dalam hal logika bisnis.
sumber
Saya tidak 100% yakin ini satu - satunya perbedaan, tetapi inilah perbedaan utama . Juga direkomendasikan untuk memiliki asosiasi dua arah oleh dokumen Hibernate:
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/best-practices.html
Secara khusus:
Saya pribadi memiliki sedikit masalah dengan rekomendasi selimut ini - menurut saya ada kasus di mana seorang anak tidak memiliki alasan praktis untuk mengetahui tentang induknya (misalnya, mengapa suatu item pesanan perlu mengetahui tentang pesanannya? terkait dengan?), tetapi saya juga melihat nilai di dalamnya dalam porsi waktu yang wajar. Dan karena dua arah tidak benar-benar merugikan apa pun, saya tidak merasa terlalu keberatan untuk dipatuhi.
sumber