web-dev-qa-db-ja.com

OracleのHibernate:StringプロパティをCLOB列にマッピングする

[〜#〜] warning [〜#〜]:以下の自分の答えを参照してください。この問題は、10.2.0.4に加えてクラスパスに存在していた古いOracleドライバーが原因で発生します。問題が解決しました。この質問の残りを後世に残します。

私は次のことに頭をぶつけてきました。これが私のアプリケーションコードから抽出された簡単なPOJOです:

_@Entity
@Table(name = "PIGGIES")
public class Piggy {    
    private Long id;
    private String description;

    public Piggy() {}

    @Id
    @GeneratedValue
    @Column(name = "PIGGY_ID")
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }

    @Lob
    @Column(name = "PIGGY_DESCRIPTION")
    public String getDescription() { return description; }
    public void setDescription(String d) { description = d; }
}
_

StringプロパティとCLOB列があります。コンテンツが短い場合(「hello world」など)、問題なく表示されます。より長い文字列を使用すると、次の例外が発生します。

_Java.sql.SQLException: operation not allowed: streams type cannot be used in batching
        at Oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.Java:134)
        at Oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.Java:179)
        at Oracle.jdbc.driver.OraclePreparedStatement.addBatch(OraclePreparedStatement.Java:4236)
        at org.Apache.commons.dbcp.DelegatingPreparedStatement.addBatch(DelegatingPreparedStatement.Java:172)
        at org.Apache.commons.dbcp.DelegatingPreparedStatement.addBatch(DelegatingPreparedStatement.Java:172)
        at org.hibernate.jdbc.BatchingBatcher.addToBatch(BatchingBatcher.Java:31)
        at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.Java:2403)
_

Oracle JDBCドライバー10.2.0.4でHibernate 3.2.3を使用しています。例外のメッセージは、バッチ処理に問題がある可能性があることを示しています。この単純なケースではバッチ処理を無効にできますが、「実際の」POJOに対して有効にする必要があります。実際、現状では、クエリのバッチ処理がHibernateを使用している唯一の理由です。

だから、私の質問は、どうすれば上記の作業を行うことができますか?

[〜#〜] edit [〜#〜]:興味深い観察:「description」プロパティの値は、1333文字以下であれば問題なく保持されます。そんな奇数!

編集2:解決策を見つけるために、getProperty()アノテーションを次のように変更しましたが、違いはありません:

_@Lob
@Type(type="text")
@Column(name = "PIGGY_DESCRIPTION", length = Integer.MAX_VALUE)
public String getDescription() { return description; }
_

編集:「PIGGIES」のDDLは次のとおりです。

_CREATE TABLE "PIGGIES" 
 (  "PIGGY_ID" NUMBER NOT NULL ENABLE, 
"PIGGY_DESCRIPTION" CLOB, 
 CONSTRAINT "PIGGIES_PK" PRIMARY KEY ("PIGGY_ID")
USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 
STORAGE(INITIAL 1048576 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "BBDATA"  ENABLE
 ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(INITIAL 1048576 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
  TABLESPACE "BBDATA" 
LOB ("PIGGY_DESCRIPTION") STORE AS "SYS_LOB0000177753C00002$$"(
TABLESPACE "BBDATA" ENABLE STORAGE IN ROW CHUNK 8192 PCTVERSION 10
NOCACHE 
STORAGE(INITIAL 1048576 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)) ;
_

そして、これがスタック全体です:

_org.hibernate.exception.GenericJDBCException: could not update: [com.bamnetworks.cms.types.Piggy#934]
    at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.Java:103)
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.Java:91)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.Java:43)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.Java:2425)
    at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.Java:2307)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.Java:2607)
    at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.Java:92)
    at org.hibernate.engine.ActionQueue.execute(ActionQueue.Java:248)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.Java:232)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.Java:140)
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.Java:298)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.Java:27)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.Java:1000)
    at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.Java:338)
    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.Java:106)
Caused by: Java.sql.SQLException: operation not allowed: streams type cannot be used in batching
    at Oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.Java:134)
    at Oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.Java:179)
    at Oracle.jdbc.driver.OraclePreparedStatement.addBatch(OraclePreparedStatement.Java:4236)
    at org.Apache.commons.dbcp.DelegatingPreparedStatement.addBatch(DelegatingPreparedStatement.Java:172)
    at org.Apache.commons.dbcp.DelegatingPreparedStatement.addBatch(DelegatingPreparedStatement.Java:172)
    at org.hibernate.jdbc.BatchingBatcher.addToBatch(BatchingBatcher.Java:31)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.Java:2403)
    ... 45 more
_
12
Max A.

Moronの警告:クラスパスに9か所のOracle JDBCクラスを持つ古いJARがあったことがわかりました。これをクリーンアップすると、次の注釈だけですべてが魔法のように機能します。

@Lob
@Column(name = "PIGGY_DESCRIPTION")
public String getDescription() { return description; }

太い指を責めなさい。

29
Max A.

@Lobアノテーションを削除して、@Columnでアノテーションを付けましたか?私の経験では、CLOBの列タイプをhibernateに指示する必要はありません。CLOBが独自に決定します。

バッチ処理を実行しているクライアントコードのスニペットを含めることができますか?

5
Jherico