Tengo una aplicación que usa hibernate 3.1 y anotaciones JPA. Tiene algunos objetos con atributos de byte [] (1k - 200k de tamaño). Utiliza la anotación JPA @Lob, e hibernate 3.1 puede leerlos perfectamente en todas las bases de datos principales; parece ocultar las peculiaridades del proveedor de JDBC Blob (como debería hacer).
@Entity
public class ConfigAttribute {
@Lob
public byte[] getValueBuffer() {
return m_valueBuffer;
}
}
Tuvimos que actualizar a 3.5, cuando descubrimos que hibernate 3.5 rompe (y no arregla) esta combinación de anotaciones en postgresql (sin solución alternativa). No he encontrado una solución clara hasta ahora, pero noté que si simplemente elimino el @Lob, usa el tipo bytea de postgresql (que funciona, pero solo en 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.
Estoy buscando una forma de tener una sola clase anotada (con una propiedad de blob) que sea portátil en las principales bases de datos.
- ¿Cuál es la forma portátil de anotar una propiedad de byte []?
- ¿Está esto arreglado en alguna versión reciente de hibernate?
Actualización: Después de leer este blog , finalmente descubrí cuál era la solución original en el problema de JIRA: Aparentemente, se supone que debes soltar @Lob y anotar la propiedad como:
@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType")
byte[] getValueBuffer() {...
Sin embargo, esto no funciona para mí , todavía obtengo OID en lugar de bytea; Sin embargo, funcionó para el autor de la edición de la JIRA, que parecía querer oid.
Después de la respuesta de A. García, probé este combo, que en realidad funciona en postgresql, pero no en Oracle.
@Type(type="org.hibernate.type.BinaryType")
byte[] getValueBuffer() {...
Lo que realmente necesito hacer es controlar qué @ org.hibernate.annotations. Escriba la combinación (@Lob + byte [] se asigna) a (en postgresql).
Aquí está el fragmento de 3.5.5.Final de MaterializedBlobType (Blob de tipo SQL). Según el blog de Steve, postgresql quiere que uses Streams para bytea (no me preguntes por qué) y el tipo de blob personalizado de postgresql para oids. Tenga en cuenta también que el uso de setBytes () en JDBC también es para bytea (de experiencias pasadas). Entonces, esto explica por qué los flujos de uso no tienen ningún efecto, ambos asumen '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 );
}
}
Esto resulta en:
ERROR: column "signature" is of type oid but expression is of type bytea
Actualización La siguiente pregunta lógica es: "¿por qué no cambiar las definiciones de la tabla manualmente a bytea" y mantener el (@Lob + byte [])? Esto hace el trabajo, HASTA intenta almacenar un byte nulo []. Lo que el controlador postgreSQL cree que es una expresión de tipo OID y el tipo de columna es bytea; esto se debe a que hibernate (correctamente) llama a JDBC.setNull () en lugar de JDBC.setBytes (nulo) que espera el controlador PG.
ERROR: column "signature" is of type bytea but expression is of type oid
El sistema de tipos en hibernación es actualmente un 'trabajo en progreso' (según el comentario de desaprobación 3.5.5). De hecho, gran parte del código 3.5.5 está desaprobado, es difícil saber qué mirar al subclasificar PostgreSQLDialect).
AFAKT, Types.BLOB / 'oid' en postgresql debe asignarse a algún tipo personalizado que utilice acceso JDBC de estilo OID (es decir, objeto PostgresqlBlobType y NO MaterializedBlobType). En realidad, nunca usé Blobs con éxito con postgresql, pero sé que bytea simplemente funciona como uno / esperaría.
Actualmente estoy viendo la BatchUpdateException; es posible que el controlador no admita el procesamiento por lotes.
Gran cita de 2004: "Para resumir mis divagaciones, diría que deberíamos esperar a que el controlador JDBC realice las LOB correctamente antes de cambiar Hibernate".
Referencias:
- 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/