0

オラクル DB。

Hibernate を使用した Spring JPA。

Clob 値をネイティブ SQL クエリに挿入するのが困難です。クエリを呼び出すコードは次のとおりです。

@SuppressWarnings("unchecked")
public List<Object[]> findQueryColumnsByNativeQuery(String queryString, Map<String, Object> namedParameters)
{
    List<Object[]> result = null;

    final Query query = em.createNativeQuery(queryString);

    if (namedParameters != null)
    {
        Set<String> keys = namedParameters.keySet();
        for (String key : keys)
        {
            final Object value = namedParameters.get(key);

            query.setParameter(key, value);

        }
    }
    query.setHint(QueryHints.HINT_READONLY, Boolean.TRUE);
    result = query.getResultList();
    return result;
}

クエリ文字列は次の形式です

SELECT  COUNT  (  DISTINCT  ( <column>  )  )   FROM  <Table> c  where (exact ( <column> ,  (:clobValue),  null  )  =  1 )

ここで、「(exact ( , (:clobValue), null ) = 1 )」は関数で、「clobValue」は Clob です。

次のように動作するようにクエリを調整できます。

SELECT  COUNT  (  DISTINCT  ( <column>  )  )   FROM  <Table> c  where (exact ( <column> ,  to_clob((:stringValue)),  null  )  =  1 )

「stringValue」は文字列ですが、明らかにこれは最大のSQL文字列サイズ(4000)までしか機能せず、それ以上のものを渡す必要があります。

  1. メソッドを使用して Clob 値を java.sql.Clob として渡そうとしました

    最終 Clob clobValue = org.hibernate.engine.jdbc.ClobProxy.generateProxy(stringValue);

これにより、
java.io.NotSerializableException: org.hibernate.engine.jdbc.ClobProxyが発生します。

  1. を使用してClobをシリアライズしようとしました

    最終 Clob clob = org.hibernate.engine.jdbc.ClobProxy.generateProxy(stringValue);
    最終クロブ clobValue = SerializableClobProxy.generateProxy(clob);

しかし、これは「正確な」関数に間違ったタイプの引数を提供しているようで、結果として
(org.hibernate.engine.jdbc.spi.SqlExceptionHelper:144) - SQL エラー: 29900、SQLState: 99999 (org.hibernate.engine.jdbc .spi.SqlExceptionHelper:146) - ORA-29900: 演算子バインディングが存在しません ORA-06553: PLS-306: 'EXACT' の呼び出しで引数の数またはタイプが正しくありません

  1. エンティティでの Clob の使用に関する投稿を読んだ後、byte[] を渡そうとしましたが、これも間違った引数の型
    (org.hibernate.engine.jdbc.spi.SqlExceptionHelper:144) を提供します - SQL エラー: 29900、SQLState: 99999 (org.hibernate.engine.jdbc.spi.SqlExceptionHelper:146) - ORA-29900: 演算子バインディングが存在しません ORA-06553: PLS-306: 'EXACT' の呼び出しで引数の数またはタイプが正しくありません

  2. 最大文字列値を壊さない限り、値を文字列として渡すこともできます

唯一の方法は「プレーンな古い JDBC」を使用することであることを示唆しているように思われる投稿 ( Using function in where clause with clob parameter ) を見ました。これはオプションではありません。私は厳しい締め切りに直面しているので、どんな助けも大歓迎です.

4

3 に答える 3

2

残念ながら、Oracle の CLOB に関するあなたの仮定は間違っています。Oracle CLOB ロケータでは、ファイル ハンドルのようなものです。そして、そのようなハンドルはデータベースによってのみ作成できます。したがって、単純に CLOB をバインド変数として渡すことはできません。CLOB は、最大 176 TB を占有する可能性があり、そのようなものは Java ヒープに保持できないため、何らかの形でデータベース ストレージに関連している必要があります。

したがって、通常のアプローチは、DB 関数 empty_clob() または dbms_lob.create_temporary (何らかの形式で) を呼び出すことです。次に、 「IN」パラメーターだと思っていても、データベースからclob を取得します。次に、そのロケーター (ハンドル、CLOB) に必要な数のデータを書き込むことができ、この CLOB を照会のパラメーターとして使用できます。

このパターンに従わない場合、コードは機能しません。JPA、SpringBatch、JDBC のいずれを使用するかは問題ではありません。この制約はデータベースによって与えられます。

于 2016-05-15T16:58:15.747 に答える
0

このような場合、Hibernate に対して明示的にパラメータの型を設定する必要があるようです。次のコードは私のために働いた:

Clob clob = entityManager
    .unwrap(Session.class)
    .getLobHelper()
    .createClob(reader, length);
int inserted = entityManager
    .unwrap(org.hibernate.Session.class)
    .createSQLQuery("INSERT INTO EXAMPLE ( UUID,  TYPE,  DATA) VALUES         (:uuid, :type, :data)")
    .setParameter("uuid", java.util.Uuid.randomUUID(), org.hibernate.type.UUIDBinaryType.INSTANCE)
    .setParameter("type", java.util.Uuid.randomUUID(), org.hibernate.type.StringType.INSTANCE)
    .setParameter("data", clob, org.hibernate.type.ClobType.INSTANCE)
    .executeUpdate();

同様の回避策が Blob にも利用できます。

于 2016-05-15T16:03:39.170 に答える
-2

答え: お二方、ご回答ありがとうございます。少し前に問題を解決したときに、これを更新する必要がありました。結局、私は JDBC を使用し、問題は煙のように消えました!

于 2016-05-25T10:49:49.213 に答える