Ho un'applicazione che utilizza hibernate 3.1 e annotazioni JPA. Ha alcuni oggetti con attributi byte [] (dimensioni da 1k a 200k). Utilizza l'annotazione JPA @Lob e hibernate 3.1 può leggerli bene su tutti i principali database - sembra nascondere le peculiarità del fornitore JDBC Blob (come dovrebbe fare).
@Entity
public class ConfigAttribute {
@Lob
public byte[] getValueBuffer() {
return m_valueBuffer;
}
}
Abbiamo dovuto aggiornare a 3.5, quando abbiamo scoperto che ibernazione 3.5 interrompe (e non risolverà) questa combinazione di annotazioni in postgresql (senza soluzione alternativa). Finora non ho trovato una soluzione chiara, ma ho notato che se rimuovo @Lob, viene utilizzato il tipo postgresql bytea (che funziona, ma solo su 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.
Sto cercando un modo per avere una singola classe annotata (con una proprietà blob) che sia portabile tra i principali database.
- Qual è il modo portabile per annotare una proprietà byte []?
- È stato risolto in qualche versione recente di ibernazione?
Aggiornamento: dopo aver letto questo blog ho finalmente capito quale fosse la soluzione originale nel problema JIRA: apparentemente dovresti eliminare @Lob e annotare la proprietà come:
@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType")
byte[] getValueBuffer() {...
Tuttavia, questo non funziona per me - ottengo ancora OID invece di bytea; tuttavia ha funzionato per l'autore del numero di JIRA, che sembrava volere oid.
Dopo la risposta di A. Garcia, ho quindi provato questa combinazione, che in realtà funziona su postgresql, ma non su Oracle.
@Type(type="org.hibernate.type.BinaryType")
byte[] getValueBuffer() {...
Quello che ho davvero bisogno di fare è controllare quale @ org.hibernate.annotations. Digita la combinazione (@Lob + byte [] viene mappata) su (su postgresql).
Di seguito è riportato lo snippet di 3.5.5.Final da MaterializedBlobType (sql tipo Blob). Secondo il blog di Steve, postgresql vuole che tu usi Streams per bytea (non chiedermi perché) e il tipo Blob personalizzato di postgresql per oids. Nota anche che l'uso di setBytes () su JDBC è anche per bytea (dall'esperienza passata). Quindi questo spiega perché use-stream non ha alcun effetto che entrambi assumono "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 );
}
}
Questo risulta in:
ERROR: column "signature" is of type oid but expression is of type bytea
Aggiorna La prossima domanda logica è: "perché non modificare manualmente le definizioni della tabella in bytea" e mantenere (@Lob + byte [])? Questo funziona, FINO a quando non si tenta di memorizzare un byte nullo []. Che il driver postgreSQL pensa sia un'espressione di tipo OID e il tipo di colonna è bytea - questo perché hibernate (giustamente) chiama JDBC.setNull () invece di JDBC.setBytes (null) che il driver PG si aspetta.
ERROR: column "signature" is of type bytea but expression is of type oid
Il sistema di tipi in ibernazione è attualmente un "work in progress" (secondo il commento di deprecazione 3.5.5). In effetti gran parte del codice 3.5.5 è deprecato, è difficile sapere cosa guardare quando si sottoclasse PostgreSQLDialect).
AFAKT, Types.BLOB / 'oid' su postgresql dovrebbe essere mappato su un tipo personalizzato che utilizza l'accesso JDBC in stile OID (cioè l'oggetto PostgresqlBlobType e NOT MaterializedBlobType). In realtà non ho mai usato con successo Blob con postgresql, ma so che bytea funziona semplicemente come uno / mi aspetterei.
Al momento sto esaminando BatchUpdateException: è possibile che il driver non supporti il batch.
Ottima citazione del 2004: "Per riassumere le mie divagazioni, direi che dovremmo aspettare che il driver JDBC esegua correttamente i LOB prima di cambiare Hibernate."
Riferimenti:
- 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/