web-dev-qa-db-ja.com

Hibernate Annotationsを使用しないPostgreSQLのテキストタイプのJPAアノテーションの修正

私は次を使用してアプリケーションを開発しています:

  • Java 1.7
  • JPA(javaee-api 7.0に含まれる)
  • Hibernate 4.3.8。最終
  • PostgreSQL-JDBC 9.4-1200-jdbc41
  • PostgreSQL 9.3.6

また、一部の文字列属性にPostgreSQLテキストデータ型を使用したいと思います。私の知る限り、JPAではこれはPostgreSQLでテキストを使用するための正しい注釈である必要があります。

@Entity
public class Product{
    ...
    @Lob
    private String description;
    ....
}

このようにエンティティに注釈を付けると、次のようなエラーが発生します。 http://www.shredzone.de/cilla/page/299/string-lobs-on-postgresql-with-hibernate-36 .html

要するに、休止状態とjdbcは、clob/text-typesに手をつないではいけないようです。

説明されているソリューションは機能しています:

@Entity
public class Product{
    ...
    @Lob
    @Type(type = "org.hibernate.type.TextType")
    private String description;
    ...
}

しかし、これには重大な欠点があります。ソースコードはコンパイル時に休止状態にする必要があり、これは不要なはずです(そもそもJPAを使用する理由の1つです)。

別の方法は、次のように列注釈を使用することです。

@Entity
public class Product{
    ...
    @Column(columnDefinition = "text")
    private String description;
    ...
}

これはうまく機能しますが、テキストタイプ(およびテキストとも呼ばれます)を持つデータベースにこだわっています。また、将来別のデータベースが使用される場合、注釈は簡単に見落とされる可能性があります。したがって、データ型はStringで定義されているため、実行前に検出できないため、発生する可能性のあるエラーを見つけるのは困難です。

とても簡単な解決策はありますか、私にはわかりませんか? JPAをHibernateおよびPostgreSQLと組み合わせて使用​​しているのは私だけではないことを確信しています。ですから、このような質問をこれ以上見つけることができないと少し混乱しています。

質問を完了するために、persistence.xmlは次のようになります。

<?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>

UPDATE:

27
knoe

text型はSQL標準の一部ではないため、公式のJPAの方法はありません。

ただし、text型はvarcharと非常に似ていますが、長さの制限はありません。 @Columnlengthプロパティを使用して、JPAの実装にヒントを与えることができます。

@Column(length=10485760)
private String description;

更新:10 MiBは、postgresqlのvarcharの最大長のようです。 textalmost無制限で、 ドキュメント に従います:

いずれにせよ、保存できる最長の文字列は約1 GBです。

6
holmis83

この注釈を追加する必要がありました。

@Column(columnDefinition="TEXT")

それ自体では機能しませんでした。データベースにテーブルを再作成する必要がありました。

DROP TABLE yourtableまたは列タイプをtextに変更しますALTER TABLEステートメント

2
Eliska P.

プレーンなJPAを使用する場合は、次のように、使用されているCLOBタイプをダイアレクトに再マップできます。

public class PGSQLMapDialect extends PostgreSQL9Dialect {


  @Override
  public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
    if (Types.CLOB == sqlTypeDescriptor.getSqlType()) {
      return LongVarcharTypeDescriptor.INSTANCE;
    }
    return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
  }


}

そのため、列にOID=を使用し、ラージオブジェクト処理を介してテキストを格納/ロードするJDBCドライバーからのCLOBマッピングは使用しません。 VarcharTypeDescriptorクラスを介したPostgres JDBCドライバーのcreatetテキスト列。

2
Torsten Krah

単純なprivate String description;。列タイプは、コードからデータベースを生成する場合にのみ問題になります。列タイプはvarcharではなくtextとして生成されるためです。

データベースに依存しない方法で、JPAベンダー固有のものなしでコーディングするのは素晴らしいことですが、これが不可能な場合もあります。現実には、複数のデータベースタイプとそのすべての詳細をサポートする必要がある場合、どこかでそれらの詳細を考慮する必要があります。 1つのオプションは、列タイプの定義にcolumnDefinitionを使用することです。もう1つの方法は、コードをそのままにして、データベースの列タイプを変更するだけです。私は2番目のものを好む。

1
Predrag Maric