Je développe une application en utilisant:
Et je voudrais utiliser le type de données texte PostgreSQL pour certains attributs String. Pour autant que je sache, en JPA, cela devrait être l'annotation correcte, pour utiliser du texte dans PostgreSQL:
@Entity
public class Product{
...
@Lob
private String description;
....
}
Lorsque j'annote mon entité comme ceci, je rencontre des erreurs qui ressemblent à ceci: http://www.shredzone.de/cilla/page/299/string-lobs-on-postgresql-with-hibernate-36 .html
En bref: Il semble que hibernate et jdbc ne vont pas de pair pour les types clob/text.
La solution décrite fonctionne:
@Entity
public class Product{
...
@Lob
@Type(type = "org.hibernate.type.TextType")
private String description;
...
}
Mais cela a un inconvénient important: le code source doit être mis en veille prolongée au moment de la compilation, ce qui ne devrait pas être nécessaire (c'est une des raisons d'utiliser JPA en premier lieu).
Une autre façon consiste à utiliser l'annotation de colonne comme ceci:
@Entity
public class Product{
...
@Column(columnDefinition = "text")
private String description;
...
}
Ce qui fonctionne bien, MAIS: Maintenant, je suis coincé avec des bases de données qui ont un type de texte (et est également appelé texte;)) et si une autre base de données sera utilisée à l'avenir, les annotations peuvent être facilement ignorées. Ainsi, l'erreur possible peut être difficile à trouver, car le type de données est défini dans une chaîne et ne peut donc pas être trouvé avant l'exécution.
Existe-t-il une solution si simple que je ne la vois tout simplement pas? Je suis très sûr que je ne suis pas le seul à utiliser JPA en combinaison avec Hibernate et PostgreSQL. Je suis donc un peu confus de ne pas pouvoir trouver plus de questions comme celle-ci.
Pour terminer la question, le fichier persistence.xml ressemble à ceci:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://Java.Sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://Java.Sun.com/xml/ns/persistence
http://Java.Sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="entityManager">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.app.model.Product</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
<property name="javax.persistence.jdbc.url"
value="jdbc:postgresql://localhost:5432/awesomedb" />
<property name="javax.persistence.jdbc.user" value="usr" />
<property name="javax.persistence.jdbc.password" value="pwd" />
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
<property name="hibernate.jdbc.use_streams_for_binary" value="false" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="show_sql" value="true" />
</properties>
</persistence-unit>
</persistence>
MISE À JOUR:
Ce problème est plus ou moins équivalent à cette question, la réponse choisie est la deuxième façon de le faire décrite dans cette question, ce que je n'aime pas en raison de la dépendance d'exécution en veille prolongée: stocker des chaînes de longueur arbitraire dans Postgresql
Cela semble être en quelque sorte lié à: https://hibernate.atlassian.net/browse/JPA-48
Étant donné que le type text
ne fait pas partie du standard SQL, il n'y a aucun moyen JPA officiel, je suppose.
Cependant, le type text
est assez similaire à varchar
, mais sans la limite de longueur. Vous pouvez suggérer l'implémentation JPA avec la propriété length
de @Column
:
@Column(length=10485760)
private String description;
Mise à jour: 10 Mio semble être la longueur maximale pour varchar
en postgresql. Le text
est presque illimité, selon le documentation :
Dans tous les cas, la chaîne de caractères la plus longue pouvant être stockée est d'environ 1 Go.
Je devais juste ajouter cette annotation:
@Column(columnDefinition="TEXT")
Cela n'a pas fonctionné tout seul. J'ai dû recréer la table dans la base de données.
DROP TABLE yourtable
ou modifiez simplement le type de colonne en text
avec ALTER TABLE
instruction
Si vous souhaitez utiliser du JPA ordinaire, vous pouvez simplement remapper le type CLOB utilisé sur le dialecte comme ceci:
public class PGSQLMapDialect extends PostgreSQL9Dialect {
@Override
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
if (Types.CLOB == sqlTypeDescriptor.getSqlType()) {
return LongVarcharTypeDescriptor.INSTANCE;
}
return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
}
}
Donc, il n'utilisera pas le mappage CLOB du pilote JDBC qui utilise un OID pour la colonne et stocke/charge le texte via la gestion des objets volumineux. Cela se traduirait simplement par des appels setString et getString sur la colonne de texte de la créature sur le pilote JDBC Postgres via la classe VarcharTypeDescriptor.
J'irais avec simple private String description;
. Le type de colonne n'est un problème que si vous générez la base de données à partir de votre code, car elle sera générée en tant que varchar
au lieu de text
.
C'est génial de coder de manière indépendante de la base de données et sans aucun élément spécifique au fournisseur JPA, mais il y a des cas où cela n'est tout simplement pas possible. Si la réalité est que vous devrez prendre en charge plusieurs types de bases de données avec toutes leurs spécificités, alors vous devrez tenir compte de ces spécificités quelque part. Une option consiste à utiliser columnDefinition
pour définir le type de colonne. Une autre consiste à laisser le code tel quel et à changer simplement le type de colonne dans la base de données. Je préfère le second.