2009-10-29 52 views
9

警告:請參閱下面我自己的回答。除10.2.0.4之外,該問題是由類路徑中存在的舊Oracle驅動程序引起的。問題解決了。留下這個問題的其餘部分爲後人。Hibernate on Oracle:將字符串屬性映射到CLOB列

我一直在抨擊以下。下面是從我的應用程序代碼蒸餾的簡單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) 

我使用Hibernate 3.2.3與Oracle JDBC驅動程序10.2.0.4。例外消息表明配料可能存在問題。雖然我可以在這種簡單的情況下禁用批處理,但我需要啓用「真正」POJO。事實上,就目前而言,查詢批處理是我們使用Hibernate的唯一原因。

所以,我的問題是,我怎麼能做出上述工作?

編輯:有趣的觀察:只要它的長度是1333個字符或更短,我的「描述」屬性的值就會保持正常。這樣的奇數!

編輯2:在試圖找到一個解決方案,我修改了getProperty()註釋如下,這使得無差異:

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

EDIT 3:這裏的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 

回答

23

Moron警報:事實證明,我的classpath上有9個Oracle JDBC類的陳舊JAR。清理完畢後,所有內容都可以通過以下注釋神奇地發揮作用:

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

責怪胖子的手指。

4

您是否嘗試刪除@Lob註釋,並使用@Column註釋它?根據我的經驗,您不需要告訴休眠CLOB的列類型,它將自行確定它。

您能否包含正在執行批處理操作的客戶端代碼片段?

+0

我給你的建議一試,我們會在幾分鐘內發現。關於批處理,我自己的代碼中沒有任何批處理。這是一個內置的休眠功能。我們在應用中使用了關聯的@BatchSize註釋。如果你看看我的問題中的堆棧跟蹤,你可以看到Hibernate經歷的所有批處理調用。 – 2009-10-29 16:16:16

+0

不,刪除@Lob,只是離開@Column和@Type沒有幫助。爲了隔離的目的,我使用@BatchSize(size = 0)註釋了類本身,即使它不是一個可接受的整體行爲過程。 – 2009-10-29 16:18:37

+0

@BatchSize(size = 0)技巧也沒有幫助。 – 2009-10-29 16:25:37

相關問題