Java 休眠 > CLOB > Oracle :(

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1843484/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 23:14:28  来源:igfitidea点击:

Hibernate > CLOB > Oracle :(

javaoraclehibernateoracle9iclob

提问by Mark

I am trying to write to an Oracle clob field a value over 4000 characters. This seams to be a common issue but non of the solutions seem to work. So I pray for help from here.

我正在尝试向 Oracle clob 字段写入超过 4000 个字符的值。这似乎是一个常见问题,但似乎没有任何解决方案有效。所以我在这里祈求帮助。

Down and dirty info:
Using Oracle 9.2.0.8.0
Hibernate3 implementing pojo's with annotations
Tomcat 6.0.16
Oracle 10.2.x drivers
C3P0 connction pool provider


故障和脏信息:使用 Oracle 9.2.0.8.0
Hibernate3 实现带有注释的 pojo
Tomcat 6.0.16
Oracle 10.2.x 驱动程序
C3P0 连接池提供程序

In my persistence.xml I have:

在我的 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>

The getter and setter looks like:

getter 和 setter 看起来像:

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

The exception I am getting is:

我得到的例外是:

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)
...

If I need to give more info pleas ask. Everything works until the dreaded limit is exceeded.

如果我需要提供更多信息,请询问。一切正常,直到超出可怕的限制。

采纳答案by Mark

Thanks to non sequitor for all the help. I have this working and figure I will put all the pieces here for future reference. Regardless of all the claims about upgrading the drivers and everything would work, non of that worked for me. In the end I had to implement a 'org.hibernate.usertype.UserType' I named it the same as all the examples on the web StringClobType. Save for some imports I used the example from Using Clobs/Blobs with Oracle and Hibernate. As far as I am concerned ignore the "beware" claim.

感谢非 sequitor 的所有帮助。我有这个工作和数字我会把所有的部分放在这里以供将来参考。不管关于升级驱动程序的所有声明和一切都会起作用,但对我来说没有任何作用。最后,我必须实现一个“org.hibernate.usertype.UserType”,我将它命名为与 Web 上所有示例 StringClobType 相同的名称。除了一些导入,我使用了Using Clobs/Blobs with Oracle and Hibernate 中的示例。就我而言,忽略“当心”的说法。

There was one change I had to make to get merges to work. Some of the methods were not implemented in the provided code sample. Eclipse fixed it for me by stubbing them out. Cool, but the replace method needs to be actually implemented or all merges will overwrite the data with a null. Here is my implementation:

我必须进行一项更改才能使合并工作。某些方法未在提供的代码示例中实现。Eclipse 通过剔除它们为我修复了它。很酷,但是替换方法需要实际实现,否则所有合并都会用空值覆盖数据。这是我的实现:

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

I will not duplicate the class implementation here go to the above link to see it. I used the code in the third gray box. Then at the top of the pojo class I wanted to use it in I added the following after the imports

我不会在这里复制类的实现去上面的链接看。我使用了第三个灰色框中的代码。然后在 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 {  
...  
}   

Then to use the new UserType I added the annotation to my getter:

然后为了使用新的 UserType,我在 getter 中添加了注释:

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

I did not need the @Lob annotation.
In my persistence.xml the persistence-unit declaration ended looking like:

我不需要@Lob 注释。
在我的 persistence.xml 中,persistence-unit 声明的结尾看起来像:

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

The SetBigStringTryClob never worked for me and was not needed for this final implementation.

SetBigStringTryClob 从来没有为我工作过,也不需要这个最终实现。

My lesson learned is in the end it is probably better to join then to fight. It would of saved me three days.

我的教训是,最终加入然后战斗可能更好。它可以为我节省三天时间。

回答by Lluis Martinez

We had a similar problem in the past, with LONG columns instead of CLOBs. The problem was the JDBC driver, the one we use now and works fine is alt text

我们过去也遇到过类似的问题,使用 LONG 列而不是 CLOB。问题是 JDBC 驱动程序,我们现在使用的并且工作正常的驱动程序是替代文字

回答by non sequitor

I think your problem might be that you are using Oracle 9ibut Hibernate dialect is 10g. Make sure your driver,db version and dialect are all in sync because there is a 9i dialect as well org.hibernate.dialect.Oracle9iDialect

我认为您的问题可能是您使用的是Oracle 9i但 Hibernate 方言是10g。确保您的驱动程序、数据库版本和方言都同步,因为还有 9i 方言org.hibernate.dialect.Oracle9iDialect

回答by Pascal Thivent

It should be:

它应该是:

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

And not:

并不是:

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

And use the right dialect for your database (org.hibernate.dialect.Oracle9iDialect).

并为您的数据库使用正确的方言 ( org.hibernate.dialect.Oracle9iDialect)。

Also make sure that you are using the latest Oracle 10g Release 2 thin driver(10.2.0.4) or later.

还要确保您使用的是最新的Oracle 10g 第 2 版瘦驱动程序(10.2.0.4) 或更高版本。