7

Hibernate を JPA プロバイダーとして使用し、大きなオブジェクト フィールドが でマークされたクラスを持っています。

@Lob
@Type( type = "org.hibernate.type.TextType" )
private String someString;

列は次のように作成されます

SOMESTRING            LONG()             

これは PostgreSQL と MySQL で問題なく動作します。オブジェクトを永続化するときに Oracle を使用する

entityManager.persist( object );

org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update例外があります。

注釈を削除する@Type( type = "org.hibernate.type.TextType" )と、Oracle の問題は解決しますが、Hibernate/PostgreSQL でユーロ記号を LOB 文字列プロパティに格納できないで説明されているように、PostgreSQL ではエンコードの問題が発生します。

out プログラムが PostgreSQL と Oracle の両方で動作するように、大きなテキスト フィールドを定義する方法を知りたいです。純粋な JPA ソリューションが最適ですが、Hibernate 固有のソリューションでも十分です。

編集:

本当の例外:

java.sql.BatchUpdateException: ORA-22295: cannot bind more than 4000 bytes data to LOB and LONG columns in 1 statement

今、見逃した例外が問題を説明しており、実際、私が保持しているオブジェクトには大きな文字列(少なくとも1つの長いDBID)以上のものがあります。

4

5 に答える 5

4

これは私にとってはうまくいきました。次のように PostgreSQL81Dialect を拡張します。

public class MyPostgreSQL81Dialect extends PostgreSQL81Dialect
{

  @Override
  public SqlTypeDescriptor getSqlTypeDescriptorOverride(int sqlCode)
  {
    SqlTypeDescriptor descriptor;
    switch (sqlCode)
    {
      case Types.CLOB:
      {
        descriptor = LongVarcharTypeDescriptor.INSTANCE;
        break;
      }
      default:
      {
        descriptor = super.getSqlTypeDescriptorOverride(sqlCode);
        break;
      }
    }  
    return descriptor;
  }

}
于 2013-12-13T07:35:25.443 に答える
3

クレジットは別の場所に移動する必要があります (@liecno という名前のユーザーに) が、次の回答での (彼の) コメントの 1 つに基づいています

@Lob
@Type(type="org.hibernate.type.StringClobType")
private String someString;

アップデート:

OK、いくつかのテストの後、すべてのシナリオで機能するさらに最新のソリューションにたどり着きました。org.hibernate.type.StringClobType推奨されていない (hibernate 4.2.x) ため、代わりに移動しました: org.hibernate.type.MaterializedClobType.

@Lob
@Type(type="org.hibernate.type.MaterializedClobType")
private String someString;
于 2014-02-10T10:05:59.400 に答える
1
@Lob
private String someString;

これを「マテリアライズドCLOB」として扱うようにHibernateに指示します。@LobアノテーションによるCLOB。CLOBロケーターから文字列/文字を抽出する必要があるために具体化されます。

ここでCLOBと言うときは、java.sql.Types.CLOBを意味します。したがって、JDBCタイプコード。ただし、ここではHibernateには別のレベルの間接参照があります。方言です。ダイアレクトは、タイプコードを物理データベースタイプ(スキーマエクスポート、キャスト呼び出しなどで使用)にマップする方法、およびPreparedStatement/ResultSetに対してバインド/抽出操作を実行する方法を定義できます。PostgreSQLダイアレクトはTypes.CLOBを物理的な「テキスト」データ型にマップします。Oracle Dialectsは、それを物理CLOBデータ型にマップします。MySQL方言は、それを物理的な「ロングテキスト」データ型にマップします。

于 2012-11-01T14:45:23.263 に答える
1

エラーは、Oracle が 1 回の更新でそれぞれ 4000 バイトを超える 2 つの列を処理できないことを意味します。過去に、Oracle にはすでにこれに関する問題がありました。テーブルごとに 1 つの LONG 列しか許可されていなかったバージョンを覚えています。彼らはこの問題を取り除かなかったのだろうか。(そのテーブルに 2 番目の LONG または LOB 列があるかどうかはわかりませんが、1 つあると思います。)

@Type通常、注釈を削除しても問題は解決しないと思います。あなたのテストでは、結果は 4000 バイト未満である可能性がありますが、他のデータでもエラーが発生する可能性があります。

解決策: ここでスケッチしたように、update ステートメントを 2 つのステートメントに分けたと思います (バッチ更新は引き続き可能です)。

for (many rows) {
  object.setFirstLongColumn(...);
  persist(object);
  session.flush();
  object.setSecondLongColumn(...);
  persist(object);
  session.flush();
}
commit();

これsession.flush()は、Hibernate がデータベース ステートメントの順序を変更してロジックに干渉するのを防ぐために必要です。

もう 1 つ: LONG はOracle では非推奨です。運が良ければ、データベースで LONG を LOB に置き換えることで問題が解決します。

于 2012-10-30T10:15:14.053 に答える
1

同様の問題があり、唯一の方法はOracle方言を拡張/カスタマイズすることでした。

于 2012-11-01T10:21:41.430 に答える