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/
Réponses:
Cela dépend de ce que vous voulez. JPA peut conserver un fichier non annoté
byte[]
. À partir de la spécification JPA 2.0:Et Hibernate mappera un it "par défaut" vers un SQL
VARBINARY
(ou un SQLLONGVARBINARY
selon laColumn
taille?) Que PostgreSQL gère avec unbytea
.Mais si vous voulez que le
byte[]
soit stocké dans un grand objet, vous devez utiliser un fichier@Lob
. De la spécification:Et Hibernate le mappera à un SQL
BLOB
que PostgreSQL gère avec unoid
.Eh bien, le problème est que je ne sais pas exactement quel est le problème. Mais je peux au moins dire que rien n'a changé depuis 3.5.0-Beta-2 (où un changement a été introduit) dans la branche 3.5.x.
Mais ma compréhension des problèmes tels que HHH-4876 , HHH-4617 et PostgreSQL et BLOB (mentionnés dans le javadoc du
PostgreSQLDialect
) est que vous êtes censé définir la propriété suivantesi vous voulez utiliser
oid
iebyte[]
avec@Lob
(ce que je comprends puisque ceVARBINARY
n'est pas ce que vous voulez avec Oracle). Avez-vous essayé cela?Comme alternative, HHH-4876 suggère d'utiliser la version obsolète
PrimitiveByteArrayBlobType
pour obtenir l'ancien comportement (avant Hibernate 3.5).Références
Ressources
la source
hibernate.jdbc.use_streams_for_binary=false
? (va vérifier ce que Steve a dit maintenant).Voici ce que dit O'reilly Enterprise JavaBeans, 3.0
Voici le code source de PostgreSQLDialect
Alors qu'est-ce que tu peux faire
Remplacez PostgreSQLDialect comme suit
Maintenant, définissez simplement votre dialecte personnalisé
Et utilisez votre annotation JPA @Lob portable
METTRE À JOUR
Ici a été extrait ici
...
qui peut être expliqué ici
...
Intéressant est parce que quand il mappe Types.BOLB comme bytea (Voir CustomPostgreSQLDialect) Il obtient
lors de l'insertion ou de la mise à jour
la source
J'utilise Hibernate 4.2.7.SP1 avec Postgres 9.3 et ce qui suit fonctionne pour moi:
car Oracle n'a aucun problème avec cela, et pour Postgres, j'utilise un dialecte personnalisé:
l'avantage de cette solution que je considère, que je peux garder les pots de mise en veille prolongée intacts.
Pour plus de problèmes de compatibilité Postgres / Oracle avec Hibernate, consultez mon article de blog .
la source
J'ai enfin réussi à faire fonctionner ça. Il étend la solution de A. Garcia, cependant, puisque le problème réside dans le type de mise en veille prolongée de type MaterializedBlob, il ne suffit pas de mapper Blob> bytea, nous avons besoin d'un remplacement pour MaterializedBlobType qui fonctionne avec le support des blob cassés en veille prolongée. Cette implémentation ne fonctionne qu'avec bytea, mais peut-être que le gars du problème JIRA qui voulait OID pourrait contribuer à une implémentation OID.
Malheureusement, le remplacement de ces types au moment de l'exécution est une douleur, car ils devraient faire partie du dialecte. Si seulement cette amélioration JIRA entre dans la version 3.6, ce serait possible.
Une grande partie de cela pourrait probablement être statique (getBinder () a-t-il vraiment besoin d'une nouvelle instance?), Mais je ne comprends pas vraiment la mise en veille prolongée, donc il s'agit principalement de copier + coller + modifier.
la source
J'ai résolu mon problème en ajoutant l'annotation de @Lob qui créera l'octet [] dans l'oracle en tant que blob, mais cette annotation créera le champ comme oid qui ne fonctionnera pas correctement, Pour rendre l'octet [] créé en tant que bytea, j'ai créé un dialecte client pour postgres comme ci-dessous
Besoin également de remplacer le paramètre pour le dialecte
spring.jpa.properties.hibernate.dialect = com.ntg.common.DBCompatibilityHelper.PostgreSQLDialectCustom
plus d'indices peuvent être trouvés sur elle: https://dzone.com/articles/postgres-and-oracle
la source
Je l'ai fait fonctionner en remplaçant l'annotation avec un fichier XML pour Postgres. L'annotation est conservée pour Oracle. À mon avis, dans ce cas, il serait préférable de remplacer le mappage de cette entité problématique avec le mappage xml. Nous pouvons remplacer des entités simples / multiples avec un mappage xml. Nous utiliserions donc des annotations pour notre base de données principalement prise en charge et un fichier xml pour chaque autre base de données.
Remarque: nous avons juste besoin de remplacer une seule classe, donc ce n'est pas un gros problème. Lire la suite de mon exemple Exemple pour remplacer l'annotation avec XML
la source
Sur Postgres, @Lob est interrompu pour l'octet [] alors qu'il tente de l'enregistrer en tant qu'oid, et pour String, le même problème se produit. Le code ci-dessous se brise sur postgres qui fonctionne bien sur oracle.
et
Afin de corriger ci-dessus sur postgres, j'ai écrit ci-dessous hibernate.dialect personnalisé
Maintenant, configurez le dialecte personnalisé en veille prolongée
XYZ est le nom du package.
Maintenant, cela fonctionne bien. REMARQUE - My Hibernate version - 5.2.8.Final Postgres version - 9.6.3
la source
Merci Justin, Pascal de m'avoir guidé dans la bonne direction. J'étais également confronté au même problème avec Hibernate 3.5.3. Vos recherches et vos pointeurs vers les bonnes classes m'ont aidé à identifier le problème et à résoudre le problème.
Pour le bénéfice de ceux qui sont toujours bloqués avec Hibernate 3.5 et qui utilisent la combinaison oid + byte [] + @LoB, voici ce que j'ai fait pour résoudre le problème.
J'ai créé un BlobType personnalisé étendant MaterializedBlobType et remplaçant l'ensemble et les méthodes get avec l'accès de style oid.
Enregistrez le CustomBlobType avec Hibernate. Voici ce que j'ai fait pour y parvenir.
la source