Pertama, beberapa klarifikasi untuk jawaban KLE :
Asosiasi tak terbatas (nullable) satu-ke-satu adalah satu-satunya yang tidak dapat diproksi tanpa instrumentasi bytecode. Alasan untuk ini adalah bahwa entitas pemilik HARUS tahu apakah properti asosiasi harus berisi objek proxy atau NULL dan tidak dapat menentukan bahwa dengan melihat kolom tabel dasarnya karena satu-ke-satu yang biasanya dipetakan melalui PK bersama, sehingga harus bersemangat diambil pula membuat proxy tidak berguna. Berikut penjelasan yang lebih detail .
banyak-ke-satu asosiasi (dan satu-ke-banyak, jelas) tidak menderita masalah ini. Entitas pemilik dapat dengan mudah memeriksa FK-nya sendiri (dan dalam kasus satu-ke-banyak, proksi pengumpulan kosong dibuat pada awalnya dan diisi sesuai permintaan), sehingga asosiasi dapat menjadi malas.
Mengganti satu-ke-satu dengan satu-ke-banyak hampir tidak pernah merupakan ide yang baik. Anda dapat menggantinya dengan banyak-ke-satu yang unik tetapi ada opsi lain (mungkin lebih baik).
Rob H. memiliki poin yang valid, namun Anda mungkin tidak dapat mengimplementasikannya tergantung pada model Anda (misalnya jika asosiasi satu-ke-satu Anda dapat dibatalkan).
Sekarang, sejauh pertanyaan awal:
A) @ManyToOne(fetch=FetchType.LAZY)
harus bekerja dengan baik. Apakah Anda yakin itu tidak ditimpa dalam kueri itu sendiri? Dimungkinkan untuk menentukan join fetch
dalam HQL dan / atau secara eksplisit mengatur mode pengambilan melalui API Kriteria yang akan diutamakan daripada anotasi kelas. Jika bukan itu masalahnya dan Anda masih mengalami masalah, silakan kirim kelas, kueri, dan hasilkan SQL untuk percakapan lebih lanjut.
B) @OneToOne
lebih rumit. Jika jelas tidak dapat dibatalkan, ikuti saran Rob H. dan tentukan sebagai berikut:
@OneToOne(optional = false, fetch = FetchType.LAZY)
Jika tidak, jika Anda dapat mengubah basis data Anda (tambahkan kolom kunci asing ke tabel pemilik), lakukan dan petakan sebagai "bergabung":
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name="other_entity_fk")
public OtherEntity getOther()
dan di OtherEntity:
@OneToOne(mappedBy = "other")
public OwnerEntity getOwner()
Jika Anda tidak bisa melakukan itu (dan tidak bisa hidup dengan bersemangat mengambil) instrumentasi bytec adalah satu-satunya pilihan Anda. Namun saya harus setuju dengan CPerkins - jika Anda punya 80 !!! bergabung karena asosiasi OneToOne yang bersemangat, Anda punya masalah yang lebih besar maka ini :-)
one-to-one
dengan rumus sepertiselect other_entity.id from other_entity where id = other_entity.id
. Tentu saja, ini tidak ideal untuk kinerja permintaan.Agar pemuatan malas berfungsi pada pemetaan satu-ke-satu yang dapat dibatalkan, Anda harus membiarkan hibernate berfungsi kompilasi instrumentasi waktu dan menambahkan
@LazyToOne(value = LazyToOneOption.NO_PROXY)
relasi satu-ke-satu.Contoh Pemetaan:
Contoh ekstensi file Ant Build (untuk melakukan instrumentasi waktu kompilasi Hibernate):
sumber
LazyToOneOption.NO_PROXY
dan tidakLazyToOneOption.PROXY
?Gagasan dasar mengalahkan XToOnes di Hibernate adalah bahwa mereka tidak malas dalam banyak kasus.
Salah satu alasannya adalah, ketika Hibernate harus memutuskan untuk meletakkan proxy (dengan id) atau null,
itu tetap harus melihat ke tabel lainnya untuk bergabung. Biaya untuk mengakses tabel lain dalam database adalah signifikan, sehingga mungkin juga mengambil data untuk tabel itu pada saat itu (perilaku tidak malas), daripada mengambilnya dalam permintaan nanti yang akan membutuhkan akses kedua ke meja yang sama.
Diedit: untuk detail, silakan merujuk ke jawaban ChssPly76 . Yang ini kurang akurat dan detail, tidak ada yang bisa ditawarkan. Terima kasih ChssPly76.
sumber
Inilah sesuatu yang telah bekerja untuk saya (tanpa instrumentasi):
Alih-alih menggunakan
@OneToOne
di kedua sisi, saya menggunakan@OneToMany
di bagian terbalik dari hubungan (yang denganmappedBy
). Itu membuat properti koleksi (List
dalam contoh di bawah), tapi saya menerjemahkannya menjadi item di pengambil, membuatnya transparan kepada klien.Pengaturan ini bekerja dengan malas, yaitu, pemilihan hanya dilakukan ketika
getPrevious()
ataugetNext()
dipanggil - dan hanya satu pilih untuk setiap panggilan.Struktur tabel:
Kelas:
sumber
Seperti yang saya jelaskan di artikel ini , kecuali jika Anda menggunakan Bytecode Enhancement , Anda tidak dapat mengambil dengan malas
@OneToOne
asosiasi sisi orangtua .Namun, paling sering, Anda bahkan tidak memerlukan asosiasi sisi orang tua jika Anda gunakan
@MapsId
di sisi klien:Dengan
@MapsId
, ituid
properti di tabel anak berfungsi sebagai Primary Key dan Foreign Key ke tabel induk Primary Key.Jadi, jika Anda memiliki referensi ke
Post
entitas induk , Anda dapat dengan mudah mengambil entitas anak menggunakan pengidentifikasi entitas induk:Dengan cara ini, Anda tidak akan memiliki masalah kueri N +1 yang dapat disebabkan oleh
mappedBy
@OneToOne
asosiasi di sisi induk.sumber
Di pemetaan XML Hibernate asli, Anda bisa melakukannya dengan mendeklarasikan pemetaan satu-ke-satu dengan atribut terbatas yang disetel ke true. Saya tidak yakin apa yang setara dengan penjelasan Hibernate / JPA itu, dan pencarian cepat dari dokumen tidak memberikan jawaban, tapi mudah-mudahan itu memberi Anda petunjuk untuk melanjutkan.
sumber
@OneToOne(optional=false,fetch=FetchMode.LAZY)
Seperti yang sudah dijelaskan dengan sempurna oleh ChssPly76, proksi Hibernate tidak membantu dengan asosiasi satu-ke-satu yang tidak dibatasi (nullable), TETAPI ada trik yang dijelaskan di sini untuk menghindari mengatur instrumentasi. Idenya adalah untuk menipu Hibernate bahwa kelas entitas yang ingin kita gunakan telah diinstrumentasi: Anda instrumen secara manual dalam kode sumber. Mudah! Saya telah mengimplementasikannya dengan CGLib sebagai penyedia bytecode dan berfungsi (pastikan Anda mengkonfigurasi lazy = "no-proxy" dan fetch = "pilih", bukan "gabung", di HBM Anda).
Saya pikir ini adalah alternatif yang baik untuk instrumentasi nyata (maksud saya otomatis) ketika Anda hanya memiliki satu hubungan nullable satu yang Anda ingin membuat malas. Kelemahan utama adalah bahwa solusinya tergantung pada penyedia bytecode yang Anda gunakan, jadi komentar kelas Anda secara akurat karena Anda bisa mengubah penyedia bytecode di masa depan; tentu saja, Anda juga memodifikasi kacang model Anda karena alasan teknis dan ini tidak baik.
sumber
Pertanyaan ini cukup lama, tetapi dengan Hibernate 5.1.10, ada beberapa solusi baru yang lebih baik dan nyaman.
Pemuatan malas berfungsi kecuali untuk sisi induk dari asosiasi @OneToOne. Ini karena Hibernate tidak memiliki cara lain untuk mengetahui apakah akan menetapkan nol atau Proxy ke variabel ini. Rincian lebih lanjut dapat Anda temukan di artikel ini
sumber
Jika hubungannya tidak boleh dua arah, maka @ElementCollection mungkin lebih mudah daripada menggunakan koleksi One2Many yang malas.
sumber