web-dev-qa-db-fra.com

Annotation JPA correcte pour le type de texte de PostgreSQL sans annotations Hibernate

Je développe une application en utilisant:

  • Java 1.7
  • JPA (inclus dans javaee-api 7.0)
  • Hibernate 4.3.8.Final
  • PostgreSQL-JDBC 9.4-1200-jdbc41
  • PostgreSQL 9.3.6

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:

27
knoe

É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.

6
holmis83

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

2
Eliska P.

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.

2
Torsten Krah

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.

1
Predrag Maric