在 Oracle 上休眠:将字符串属性映射到 CLOB 列
Posted
技术标签:
【中文标题】在 Oracle 上休眠:将字符串属性映射到 CLOB 列【英文标题】:Hibernate on Oracle: mapping String property to CLOB column 【发布时间】:2010-12-11 07:14:19 【问题描述】:警告:请参阅下面的我自己的答案。该问题是由除 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 的唯一原因。
所以,我的问题是,我怎样才能使上述工作?
编辑:有趣的观察:我的“描述”属性的值只要它的长度正好为 1333 个字符或更短,就可以保持良好状态。好奇怪的数字!
EDIT 2:为了寻找解决方案,我修改了getProperty()
注解如下,没有任何区别:
@Lob
@Type(type="text")
@Column(name = "PIGGY_DESCRIPTION", length = Integer.MAX_VALUE)
public String getDescription() return description;
编辑 3:这是“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
【问题讨论】:
【参考方案1】:白痴警告:原来我的类路径上有一个陈旧的 JAR,其中包含 9 个左右的 Oracle JDBC 类。清理完之后,只需以下注释,一切都可以神奇地工作:
@Lob
@Column(name = "PIGGY_DESCRIPTION")
public String getDescription() return description;
责备胖手指。
【讨论】:
【参考方案2】:您是否尝试过删除@Lob
注释,而只使用@Column
注释它?根据我的经验,您不需要告诉休眠 CLOB 的列类型,它会自行确定。
您能否包含执行批处理操作的客户端代码的 sn-p?
【讨论】:
我正在尝试您的建议,我们会在几分钟内找到答案。关于批处理,我自己的代码中没有任何东西可以进行批处理。这是一个内置的休眠功能。我们在应用程序中的关联上使用了一个 @BatchSize 注释。如果您查看我的问题中的堆栈跟踪,您可以看到 Hibernate 经历的所有批处理调用。 不,删除@Lob 并留下@Column 和@Type 没有帮助。出于隔离目的,我已使用 @BatchSize(size=0) 对类本身进行了注释,尽管总体而言这不是可接受的操作过程。 所以在提交时抛出了错误,触发错误所需的事务中的最小操作集是什么? 我只是想保留Piggy
的一个实例。一张桌子,一排,两列。没什么大不了的。这实际上与我在真实应用程序中看到的行为完全相同,如果你愿意的话,这里有一个更大的Piggy
-s 集合。
所以你的描述必须是<= 1333
,这很奇怪,你已经通过删除代码(注释/xml)和你的属性文件?以上是关于在 Oracle 上休眠:将字符串属性映射到 CLOB 列的主要内容,如果未能解决你的问题,请参考以下文章