J'ai une application utilisant les annotations Hibernate 3.1 et JPA. Il a quelques objets avec des attributs byte [] (taille 1k - 200k). Il utilise l'annotation JPA @Lob, et hibernate 3.1 peut les lire très bien sur toutes les principales bases de données - il semble cacher les particularités du fournisseur JDBC Blob (comme il se doit).
@Entity
public class ConfigAttribute {
@Lob
public byte[] getValueBuffer() {
return m_valueBuffer;
}
}
Nous avons dû passer à la version 3.5, lorsque nous avons découvert que la mise en veille prolongée 3.5 casse (et ne corrige pas) cette combinaison d'annotations dans postgresql (sans solution de contournement). Je n'ai pas trouvé de correctif clair jusqu'à présent, mais j'ai remarqué que si je supprimais simplement le @Lob, il utilise le type postgresql bytea (qui fonctionne, mais uniquement sur 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.
Je recherche un moyen d'avoir une seule classe annotée (avec une propriété blob) qui soit portable dans les principales bases de données.
- Quelle est la manière portable d'annoter une propriété byte []?
- Est-ce corrigé dans une version récente de la mise en veille prolongée?
Mise à jour: Après avoir lu ce blog, j'ai enfin compris quelle était la solution de contournement d'origine dans le problème JIRA: Apparemment, vous êtes censé supprimer @Lob et annoter la propriété comme suit:
@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType")
byte[] getValueBuffer() {...
Cependant, cela ne fonctionne pas pour moi - j'obtiens toujours des OID au lieu de bytea; cela a cependant fonctionné pour l'auteur du numéro JIRA, qui semblait vouloir l'oid.
Après la réponse d'A. Garcia, j'ai ensuite essayé ce combo, qui fonctionne réellement sur postgresql, mais pas sur oracle.
@Type(type="org.hibernate.type.BinaryType")
byte[] getValueBuffer() {...
Ce que je dois vraiment faire est de contrôler à quel @ org.hibernate.annotations.Type la combinaison (@Lob + byte [] est mappée) à (sur postgresql).
Voici l'extrait de code 3.5.5.Final de MaterializedBlobType (sql type Blob). Selon le blog de Steve, postgresql veut que vous utilisiez Streams pour bytea (ne me demandez pas pourquoi) et le type Blob personnalisé de postgresql pour les oids. Notez également que l'utilisation de setBytes () sur JDBC est également pour bytea (d'après l'expérience passée). Cela explique donc pourquoi use-streams n'a aucun effet qu'ils supposent tous les deux «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 );
}
}
Cela se traduit par:
ERROR: column "signature" is of type oid but expression is of type bytea
Mise à jour La question logique suivante est: "pourquoi ne pas simplement changer les définitions de table manuellement en bytea" et conserver le (@Lob + byte [])? Cela fait le travail, JUSQU'AU vous essayez de stocker un octet nul []. Ce que le pilote postgreSQL pense être une expression de type OID et le type de colonne est bytea - c'est parce que hibernate appelle (à juste titre) JDBC.setNull () au lieu de JDBC.setBytes (null) que le pilote PG attend.
ERROR: column "signature" is of type bytea but expression is of type oid
Le système de types en hibernate est actuellement un «travail en cours» (selon le commentaire de dépréciation de 3.5.5). En fait, une grande partie du code 3.5.5 est obsolète, il est difficile de savoir quoi regarder lors du sous-classement de PostgreSQLDialect).
AFAKT, Types.BLOB / 'oid' sur postgresql doit être mappé à un type personnalisé qui utilise un accès JDBC de style OID (c'est-à-dire l'objet PostgresqlBlobType et NOT MaterializedBlobType). Je n'ai jamais vraiment utilisé avec succès des Blobs avec postgresql, mais je sais que bytea fonctionne simplement comme je m'y attendais.
Je regarde actuellement l'exception BatchUpdateException - il est possible que le pilote ne prenne pas en charge le traitement par lots.
Excellente citation de 2004: "Pour résumer mes divagations, je dirais qu'ils devraient attendre que le pilote JDBC fasse correctement les LOB avant de changer Hibernate."
Références:
- 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/