Hibernate › CLOB › Oracle :(

Я пытаюсь записать в поле clob Oracle значение более 4000 символов. Это кажется распространенной проблемой, но ни одно из решений не работает. Поэтому я молюсь о помощи отсюда.

Устаревшая информация:
Использование Oracle 9.2.0.8.0
Hibernate3, реализация pojo с аннотациями
Tomcat 6.0.16
Драйверы Oracle 10.2.x
Поставщик пула подключений C3P0

В моем файле persistence.xml у меня есть:

<persistence-unit name="DWEB" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <properties>
        <property name="hibernate.archive.autodetection" value="class"/> 
        <property name="hibernate.connection.password" value="###" />
        <property name="hibernate.connection.username" value="###" />
        <property name="hibernate.default_schema" value="schema" />
        <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
        <property name="hibernate.c3p0.min_size" value="5" />
        <property name="hibernate.c3p0.max_size" value="20" />
        <property name="hibernate.c3p0.timeout" value="300" />
        <property name="hibernate.c3p0.max_statements" value="50" />
        <property name="hibernate.c3p0.idle_test_period" value="3000" />
        <property name="show_sql" value="true" />
        <property name="format_sql" value="true" />
        <property name="use_sql_comments" value="true" />
        <property name="SetBigStringTryClob" value="true"/>
        <property name="hibernate.jdbc.batch_size" value="0"/>
        <property name="hibernate.connection.url" value="jdbc:oracle:thin:@server.ss.com:1521:DDD"/>
        <property name="hibernate.connection.driver_class" value="oracle.jdbc.driver.OracleDriver"/>
    </properties>
</persistence-unit>

Геттер и сеттер выглядят так:

@Lob 
@Column(name="COMMENT_DOC")
public String getDocument(){
    return get("Document");
}
public void setDocument(String s){
    put("Document",s);
}

Исключение, которое я получаю:

SEVERE: Servlet.service() for servlet SW threw exception
java.sql.SQLException: Io exception: Software caused connection abort: socket write error
    at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134)
    at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:179)
    at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:334)
    at oracle.jdbc.ttc7.TTC7Protocol.handleIOException(TTC7Protocol.java:3678)
    at oracle.jdbc.ttc7.TTC7Protocol.doOall7(TTC7Protocol.java:1999)
    at oracle.jdbc.ttc7.TTC7Protocol.parseExecuteFetch(TTC7Protocol.java:1144)
    at oracle.jdbc.driver.OracleStatement.executeNonQuery(OracleStatement.java:2152)
    at oracle.jdbc.driver.OracleStatement.doExecuteOther(OracleStatement.java:2035)
    at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:2876)
    at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:609)
    at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:46)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2275)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2688)
    at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:79)
    at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
    at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:304)
    at org.sw.website.actions.content.AddComment.performAction(AddComment.java:60)
...

Если мне нужно дать больше информации, пожалуйста, спросите. Все работает до тех пор, пока не будет превышен страшный предел.


person Mark    schedule 03.12.2009    source источник
comment
исключение не похоже на CLOB. Возникает ли исключение при удалении CLOB?   -  person Bozho    schedule 04.12.2009
comment
Да, и это происходит только в том случае, если размер больше 4000   -  person Mark    schedule 04.12.2009
comment
Сегодня утром исключение другое. Это чаще сообщается java.sql.SQLException: больше нет данных для чтения из сокета в oracle.jdbc.dbaccess...   -  person Mark    schedule 04.12.2009


Ответы (4)


Спасибо non sequitor за помощь. У меня есть эта работа, и я помещу все части здесь для дальнейшего использования. Несмотря на все заявления об обновлении драйверов и о том, что все будет работать, у меня ничего из этого не сработало. В конце концов мне пришлось реализовать «org.hibernate.usertype.UserType». Я назвал его так же, как и все примеры в Интернете StringClobType. Сохранение для некоторого импорта Я использовал пример из Использование клобуков/блобов с Oracle и Hibernate. Что касается меня, игнорируйте утверждение «остерегайтесь».

Было одно изменение, которое мне пришлось внести, чтобы слияния заработали. Некоторые из методов не были реализованы в предоставленном образце кода. Eclipse исправила это для меня, заглушив их. Круто, но метод замены должен быть действительно реализован, иначе все слияния перезапишут данные нулевым значением. Вот моя реализация:

public Object replace(Object newValue, Object existingValue, Object arg2)throws HibernateException {
    return newValue;
}

Я не буду дублировать реализацию класса, здесь перейдите по ссылке выше, чтобы увидеть ее. Я использовал код в третьем сером поле. Затем в верхней части класса pojo я хотел использовать его, я добавил следующее после импорта

...  
import org.hibernate.annotations.Type;  
import org.hibernate.annotations.TypeDefs;  
import org.hibernate.annotations.TypeDef;  

@TypeDefs({  
    @TypeDef(  
        name="clob",  
        typeClass = foo.StringClobType.class  
    )  
})  
@Entity  
@Table(name="EA_COMMENTS")  
public class Comment extends SWDataObject implements JSONString, Serializable {  
...  
}   

Затем, чтобы использовать новый UserType, я добавил аннотацию к моему геттеру:

@Type(type="clob")
@Column(name="COMMENT_DOC")
public String getDocument(){
    return get("Document");
}

Мне не понадобилась аннотация @Lob.
В моем файле persistence.xml объявление модуля сохранения состояния выглядело так:

<persistence-unit name="###" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <properties>
        <property name="hibernate.archive.autodetection" value="class"/> 
        <property name="hibernate.connection.password" value="###" />
        <property name="hibernate.connection.username" value="###" />
        <property name="hibernate.connection.url" value="jdbc:oracle:thin:@server.something.com:1521:###"/>
        <property name="hibernate.connection.driver_class" value="oracle.jdbc.OracleDriver"/>
        <property name="hibernate.default_schema" value="###" />
        <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle9iDialect" />
        <property name="hibernate.c3p0.min_size" value="5" />
        <property name="hibernate.c3p0.max_size" value="100" />
        <property name="hibernate.c3p0.timeout" value="300" />
        <property name="hibernate.c3p0.max_statements" value="50" />
        <property name="hibernate.c3p0.idle_test period" value="3000" />
        <property name="hibernate.c3p0.idle_connection_test_period" value="300" />
        <property name="show_sql" value="false" />
        <property name="format_sql" value="false" />
        <property name="use_sql_comments" value="false" />
        <property name="hibernate.jdbc.batch_size" value="0"/>
    </properties>
</persistence-unit>

SetBigStringTryClob никогда не работал у меня и не был нужен для этой окончательной реализации.

Я усвоил урок: в конце концов, наверное, лучше присоединиться, чем сражаться. Это сэкономило бы мне три дня.

person Mark    schedule 07.12.2009
comment
Похоже, исходный пост пропал, найти его можно было только в архивах: http://web.archive.org/web/20090322003916/http://www.hibernate.org/56.html? - person Abdullah Jibaly; 05.07.2011
comment
Да, вы должны опубликовать код, а не полагаться на ссылку, оригинала больше нет. - person Steve Swinsburg; 23.01.2015

Я думаю, ваша проблема может заключаться в том, что вы используете Oracle 9i, но диалект Hibernate 10g. Убедитесь, что ваш драйвер, версия базы данных и диалект синхронизированы, потому что существует также диалект 9i org.hibernate.dialect.Oracle9iDialect

person non sequitor    schedule 04.12.2009
comment
Спасибо, начал с 9i, ​​но безрезультатно. Я вернулся и снова установил его на 9i, чтобы перепроверить. Все еще получаю то же исключение. - person Mark; 04.12.2009
comment
А как насчет драйверов, вы все еще используете драйверы для 10g, когда используете 9i? Также вы можете опубликовать сгенерированный sql? - person non sequitor; 04.12.2009
comment
Как определить, какие драйверы используются? Я использую последнюю версию ojbc14.jar с сайта оракула. Класс драйвера в файле persitence.xml — oracle.jdbc.driver.OracleDriver . Я выкопаю запущенный sql и опубликую его. - person Mark; 05.12.2009
comment
Это sql, сгенерированный hibernate: вставьте в pweb60.EA_COMMENTS (APPROVED, ARCHIVED, PATH, DELETED, COMMENT_DOC, FINISHED, MODERATED_BY, PARENT_COMMENT, TOPIC_ID, USER_ID, ID) значения (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - person Mark; 05.12.2009
comment
По вашим словам, вы используете драйверы Oracle 10.2.x. Я точно не знаю, что это такое. - person non sequitor; 05.12.2009
comment
Так я и сделал, извините за путаницу. Я только что загрузил драйверы Oracle 9.2.0.1. Все та же проблема. Конечно, у меня были надежды на секунду. - person Mark; 05.12.2009
comment
Эта проблема, кажется, повторяется в Hibernate, и я не могу поверить, что она все еще существует на форуме Hibernate, когда пользователи создали/расширили тип пользователя. Для себя я использовал Spring и typeDef-ed мой тип clob, например @org.hibernate.annotations.TypeDef( name="clob", typeClass=org.springframework.orm.hibernate3.support.ClobStringType.class ), это отлично сработало для меня в Oracle. Даже если вы не используете Spring, вы можете посмотреть источник ClobStringType, написать свой собственный класс и использовать его аналогичным образом на getDocument(), например это @org.hibernate.annotations.Type(type="clob") - person non sequitor; 05.12.2009
comment
Я видел много таких, и все они датированы примерно 2004 годом. Я пытался избежать хакерского решения. Другие утверждают, что меняют драйвер и у них все работает хорошо. Это заставляет меня поверить, что у меня проблема с конфигурацией либо в моем коде, либо, возможно, в том, как администратор базы данных настроил БД. - person Mark; 05.12.2009
comment
Отметьте, почему бы вам не перезагрузить свой Tomcat сейчас, когда все ваши драйверы, диалекты и т. д. верны, и дайте мне знать. - person non sequitor; 05.12.2009
comment
Я полагаю, что Connection.setBigStringTryClob — это функция 10g, попробуйте удалить ее из файла persistence.xml, а затем также убедитесь, что тип столбца для comment_doc в базе данных равен clob. - person non sequitor; 05.12.2009
comment
Сделал все это и проверил по вашей инструкции с небольшими изменениями. Без setBigStringTryClob я получаю исключение No more data to read from socket. Добавив его обратно, я начал разговаривать с нашим администратором базы данных, и каждый раз, когда я запускаю запрос, на сервере БД появляется дамп ошибки нарушения протокола. - person Mark; 07.12.2009
comment
Спасибо, за помощь, мне пришлось реализовать тип пользователя и теперь он работает. В конце концов, мужчина победил меня. - person Mark; 07.12.2009

Должен быть:

<property name="hibernate.connection.SetBigStringTryClob">true</property>
<property name="hibernate.jdbc.batch_size">0</property>

И не:

<property name="SetBigStringTryClob">true</property>

И используйте правильный диалект для своей базы данных (org.hibernate.dialect.Oracle9iDialect).

Также убедитесь, что вы используете последнюю версию тонкого драйвера Oracle 10g Release 2 (10.2.0.4) или более позднюю.

person Pascal Thivent    schedule 25.01.2010

У нас была похожая проблема в прошлом, с столбцами LONG вместо CLOB. Проблема заключалась в драйвере JDBC, тот, который мы сейчас используем и отлично работает, это альтернативный текст

person Lluis Martinez    schedule 04.12.2009
comment
Это банку драйверов, которую мы используем. - person Mark; 04.12.2009