Спящий режим в Oracle: сопоставление свойства String со столбцом CLOB - PullRequest
12 голосов
/ 29 октября 2009

ПРЕДУПРЕЖДЕНИЕ : см. Мой собственный ответ ниже. Проблема вызвана старыми драйверами Oracle, которые присутствовали в пути к классам в дополнение к 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. Когда содержимое короткое (например, "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.

Итак, мой вопрос, как я могу заставить работать выше?

РЕДАКТИРОВАТЬ : Интересное наблюдение: значение моего свойства "description" сохраняется очень хорошо до тех пор, пока оно ровно 1333 символа или меньше. Такое странное число!

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

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

РЕДАКТИРОВАТЬ 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

Ответы [ 2 ]

28 голосов
/ 29 октября 2009

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

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

Вини жирные пальцы.

5 голосов
/ 29 октября 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...