Saya memiliki aplikasi yang menggunakan anotasi hibernate 3.1 dan JPA. Ini memiliki beberapa objek dengan atribut byte [] (ukuran 1k - 200k). Ia menggunakan anotasi JPA @Lob, dan hibernate 3.1 dapat membacanya dengan baik di semua database utama - tampaknya menyembunyikan kekhasan vendor JDBC Blob (sebagaimana mestinya).
@Entity
public class ConfigAttribute {
@Lob
public byte[] getValueBuffer() {
return m_valueBuffer;
}
}
Kami harus meningkatkan ke 3.5, ketika kami menemukan bahwa hibernate 3.5 rusak (dan tidak akan memperbaiki) kombinasi anotasi ini di postgresql (tanpa solusi). Saya belum menemukan perbaikan yang jelas sejauh ini, tetapi saya perhatikan bahwa jika saya hanya menghapus @Lob, itu menggunakan bytea tipe postgresql (yang berfungsi, tetapi hanya pada postgres).
annotation postgres oracle works on
-------------------------------------------------------------
byte[] + @Lob oid blob oracle
byte[] bytea raw(255) postgresql
byte[] + @Type(PBA) oid blob oracle
byte[] + @Type(BT) bytea blob postgresql
once you use @Type, @Lob seems to not be relevant
note: oracle seems to have deprecated the "raw" type since 8i.
Saya mencari cara untuk memiliki kelas beranotasi tunggal (dengan properti blob) yang portabel di seluruh database utama.
- Apa cara portabel untuk menganotasi properti byte []?
- Apakah ini diperbaiki di beberapa versi hibernasi terbaru?
Pembaruan: Setelah membaca blog ini, saya akhirnya menemukan solusi asli dalam masalah JIRA: Rupanya Anda seharusnya menghapus @Lob dan memberi anotasi pada properti sebagai:
@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType")
byte[] getValueBuffer() {...
Namun, ini tidak berhasil untuk saya - saya masih mendapatkan OID, bukan bytea; namun hal itu berhasil untuk penulis masalah JIRA, yang sepertinya menginginkan oid.
Setelah jawaban dari A. Garcia, saya kemudian mencoba kombo ini, yang sebenarnya berfungsi pada postgresql, tetapi tidak pada oracle.
@Type(type="org.hibernate.type.BinaryType")
byte[] getValueBuffer() {...
Yang benar-benar perlu saya lakukan adalah mengontrol @ org.hibernate.annotations. Ketik kombinasi (@Lob + byte [] yang dipetakan) ke (di postgresql).
Berikut adalah potongan dari 3.5.5. Final dari MaterializedBlobType (sql type Blob). Menurut blog Steve, postgresql ingin Anda menggunakan Streams untuk bytea (jangan tanya saya mengapa) dan jenis Blob kustom postgresql untuk oids. Perhatikan juga bahwa menggunakan setBytes () di JDBC juga untuk bytea (dari pengalaman sebelumnya). Jadi ini menjelaskan mengapa use-stream tidak memengaruhi mereka berdua menganggap 'bytea'.
public void set(PreparedStatement st, Object value, int index) {
byte[] internalValue = toInternalFormat( value );
if ( Environment.useStreamsForBinary() ) {
// use streams = true
st.setBinaryStream( index,
new ByteArrayInputStream( internalValue ), internalValue.length );
}
else {
// use streams = false
st.setBytes( index, internalValue );
}
}
Ini menghasilkan:
ERROR: column "signature" is of type oid but expression is of type bytea
Perbarui Pertanyaan logis berikutnya adalah: "mengapa tidak mengubah definisi tabel secara manual ke bytea" dan menyimpan (@Lob + byte [])? Ini tidak bekerja, UNTIL Anda mencoba untuk menyimpan null byte []. Yang menurut driver postgreSQL adalah ekspresi tipe OID dan tipe kolom adalah bytea - ini karena hibernate (dengan benar) memanggil JDBC.setNull () dan bukan JDBC.setBytes (null) yang diharapkan driver PG.
ERROR: column "signature" is of type bytea but expression is of type oid
Sistem tipe dalam mode hibernasi saat ini sedang dalam proses (menurut komentar penghentian 3.5.5). Faktanya, begitu banyak kode 3.5.5 yang tidak digunakan lagi, sulit untuk mengetahui apa yang harus dilihat saat melakukan sub-klasifikasi PostgreSQLDialect).
AFAKT, Types.BLOB / 'oid' pada postgresql harus dipetakan ke beberapa tipe kustom yang menggunakan akses JDBC gaya OID (yaitu objek PostgresqlBlobType dan NOT MaterializedBlobType). Saya tidak pernah benar-benar berhasil menggunakan Blobs dengan postgresql, tetapi saya tahu bahwa bytea hanya berfungsi seperti yang saya harapkan.
Saat ini saya melihat BatchUpdateException - kemungkinan driver tidak mendukung batching.
Kutipan bagus dari 2004: "Untuk menyimpulkan ocehan saya, saya akan mengatakan mereka kita harus menunggu driver JDBC melakukan LOB dengan benar sebelum mengubah Hibernate."
Referensi:
- https://forum.hibernate.org/viewtopic.php?p=2393203
- https://forum.hibernate.org/viewtopic.php?p=2435174
- http://hibernate.atlassian.net/browse/HHH-4617
- http://postgresql.1045698.n5.nabble.com/Migration-to-Hibernate-3-5-final-td2175339.html
- https://jira.springframework.org/browse/SPR-2318
- https://forums.hibernate.org/viewtopic.php?p=2203382&sid=b526a17d9cf60a80f13d40cf8082aafd
- http://virgo47.wordpress.com/2008/06/13/jpa-postgresql-and-bytea-vs-oid-type/
Jawaban:
Itu tergantung pada apa yang Anda inginkan. JPA bisa tetap tanpa anotasi
byte[]
. Dari spesifikasi JPA 2.0:Dan Hibernate akan memetakannya "secara default" ke SQL
VARBINARY
(atau SQLLONGVARBINARY
tergantungColumn
ukurannya?) Yang ditangani PostgreSQL dengan filebytea
.Tetapi jika Anda ingin
byte[]
disimpan dalam Objek Besar, Anda harus menggunakan file@Lob
. Dari spesifikasi:Dan Hibernate akan memetakannya ke SQL
BLOB
yang ditangani PostgreSQL dengan fileoid
.Nah, masalahnya adalah saya tidak tahu persis apa masalahnya. Tetapi setidaknya saya dapat mengatakan bahwa tidak ada yang berubah sejak 3.5.0-Beta-2 (di mana perubahan telah diperkenalkan) di cabang 3.5.x.
Tetapi pemahaman saya tentang masalah seperti HHH-4876 , HHH-4617 dan PostgreSQL dan BLOBs (disebutkan di javadoc
PostgreSQLDialect
) adalah bahwa Anda seharusnya mengatur properti berikutjika Anda ingin menggunakan
oid
iebyte[]
with@Lob
(yang menurut pemahaman saya karenaVARBINARY
bukan yang Anda inginkan dengan Oracle). Apakah kamu sudah mencobanya?Sebagai alternatif, HHH-4876 menyarankan penggunaan usang
PrimitiveByteArrayBlobType
untuk mendapatkan perilaku lama (pra Hibernate 3.5).Referensi
Sumber daya
sumber
hibernate.jdbc.use_streams_for_binary=false
juga? (akan memeriksa apa yang dikatakan Steve sekarang).Inilah yang dikatakan oleh O'reilly Enterprise JavaBeans, 3.0
Ini dia kode sumber PostgreSQLDialect
Jadi apa yang bisa Anda lakukan
Ganti PostgreSQLDialect sebagai berikut
Sekarang tentukan saja dialek khusus Anda
Dan gunakan anotasi JPA @Lob portabel Anda
MEMPERBARUI
Berikut telah diekstrak di sini
...
yang bisa dijelaskan disini
...
Menarik karena ketika dia memetakan Type.BOLB sebagai bytea (Lihat CustomPostgreSQLDialect) Dia mendapatkan
saat memasukkan atau memperbarui
sumber
Saya menggunakan Hibernate 4.2.7.SP1 dengan Postgres 9.3 dan berikut ini berfungsi untuk saya:
karena Oracle tidak memiliki masalah dengan itu, dan untuk Postgres saya menggunakan dialek khusus:
keuntungan dari solusi ini saya anggap, bahwa saya dapat menjaga stoples hibernasi tidak tersentuh.
Untuk masalah kompatibilitas Postgres / Oracle lainnya dengan Hibernate, lihat posting blog saya .
sumber
Saya akhirnya mendapatkan ini bekerja. Ini memperluas solusi dari A. Garcia, bagaimanapun, karena masalahnya terletak pada tipe hibernate tipe MaterializedBlob hanya pemetaan Blob> bytea tidak cukup, kita memerlukan pengganti MaterializedBlobType yang bekerja dengan dukungan blob hibernate yang rusak. Implementasi ini hanya bekerja dengan bytea, tetapi mungkin orang dari masalah JIRA yang menginginkan OID dapat berkontribusi dalam implementasi OID.
Sayangnya, mengganti jenis ini saat runtime sangat merepotkan, karena mereka harus menjadi bagian dari Dialek. Kalau saja penambahan JIRA ini masuk ke 3.6 itu bisa.
Banyak dari ini mungkin bisa statis (apakah getBinder () benar-benar membutuhkan contoh baru?), Tetapi saya tidak begitu memahami hibernate internal jadi ini sebagian besar adalah salin + tempel + ubah.
sumber
saya memperbaiki masalah saya dengan menambahkan anotasi @Lob yang akan membuat byte [] di oracle sebagai blob, tetapi anotasi ini akan membuat bidang sebagai oid yang tidak berfungsi dengan baik, Untuk membuat byte [] dibuat sebagai bytea saya membuat dialek pelanggan untuk postgres seperti di bawah ini
Juga perlu mengganti parameter untuk Dialek
spring.jpa.properties.hibernate.dialect = com.ntg.common.DBCompatibilityHelper.PostgreSQLDialectCustom
lebih banyak petunjuk dapat ditemukan di: https://dzone.com/articles/postgres-and-oracle
sumber
Saya berhasil melakukannya dengan mengganti anotasi dengan file XML untuk Postgres. Anotasi disimpan untuk Oracle. Menurut pendapat saya, dalam hal ini akan lebih baik kita menimpa pemetaan masalah-beberapa enity ini dengan pemetaan xml. Kita dapat mengganti satu / beberapa entitas dengan pemetaan xml. Jadi kami akan menggunakan anotasi untuk basis data kami yang sebagian besar didukung, dan file xml untuk basis data satu sama lain.
Catatan: kita hanya perlu mengganti satu kelas, jadi ini bukan masalah besar. Baca lebih lanjut dari contoh saya Contoh untuk mengganti anotasi dengan XML
sumber
Pada Postgres @Lob melanggar byte [] saat mencoba menyimpannya sebagai oid, dan untuk String juga terjadi masalah yang sama. Kode di bawah ini melanggar postgres yang berfungsi dengan baik di oracle.
dan
Untuk memperbaiki di atas pada postgres telah menulis di bawah hibernate.dialect kustom
Sekarang konfigurasikan dialek khusus dalam mode hibernasi
XYZ adalah nama paket.
Sekarang bekerja dengan baik. CATATAN- Versi Hibernate saya - 5.2.8. Versi Postgres akhir- 9.6.3
sumber
Terima kasih Justin, Pascal karena telah membimbing saya ke arah yang benar. Saya juga menghadapi masalah yang sama dengan Hibernate 3.5.3. Penelitian dan petunjuk Anda ke kelas yang tepat telah membantu saya mengidentifikasi masalah dan melakukan perbaikan.
Untuk keuntungan bagi mereka yang masih terjebak dengan Hibernate 3.5 dan menggunakan kombinasi oid + byte [] + @LoB, berikut adalah apa yang telah saya lakukan untuk memperbaiki masalah tersebut.
Saya membuat BlobType kustom memperluas MaterializedBlobType dan menimpa set dan metode get dengan akses gaya oid.
Daftarkan CustomBlobType dengan Hibernate. Berikut adalah apa yang saya lakukan untuk mencapai itu.
sumber