Подтвердить что ты не робот

Hibernate для Oracle: отображение свойства String для столбца CLOB

ПРЕДУПРЕЖДЕНИЕ: см. мой собственный ответ ниже. Проблема вызвана старыми драйверами Oracle, которые присутствовали в classpath в дополнение к 10.2.0.4. Задача решена. Оставляя остальную часть этого вопроса для потомков.

Я бил головой о следующее. Здесь просто 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. Когда содержимое является коротким (например, "привет мир" ), оно сохраняется просто отлично. С более длинными строками я получаю следующее исключение:

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 с драйвером JDBC от Oracle 10.2.0.4. Сообщение об исключении указывает, что пакетная обработка может быть неисправна. Хотя я могу отключить пакетную обработку в этом простом случае, мне нужно включить его для "реальных" POJO. На самом деле, поскольку ситуация стоит прямо сейчас, пакетная обработка запросов является единственной причиной, по которой мы используем Hibernate вообще.

Итак, мой вопрос: как я могу сделать вышеописанную работу?

ИЗОБРАЖЕНИЕ. Интересное наблюдение: ценность моего свойства "description" сохраняется просто отлично, если оно равно 1333 символам в длину или короче. Такое нечетное число!

РЕДАКТИРОВАТЬ 2. В попытке найти решение я модифицировал аннотации getProperty() следующим образом, что не имело никакого значения:

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

EDIT 3: здесь DDL для "PIGGIES":

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
4b9b3361

Ответ 1

Предупреждение Moron: выясняется, что у меня был устаревший JAR с 9-классными классами Oracle JDBC в моем пути к классам. Убрав это, все просто волшебным образом работало с помощью следующих аннотаций:

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

Поражайте жирными пальцами.

Ответ 2

Вы пытались @Lob аннотацию @Lob и просто аннотировать ее с помощью @Column? По моему опыту, вам не нужно указывать hibernate тип столбца для CLOB, он определит его самостоятельно.

Можете ли вы включить фрагмент кода клиента, который выполняет пакетную операцию?