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.
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
In my persistence.xml I have:
<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:
#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.
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.
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:
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
...
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:
#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:
<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.
My lesson learned is in the end it is probably better to join then to fight. It would of saved me three days.
I think your problem might be that you are using Oracle 9i but 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
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).
Also make sure that you are using the latest Oracle 10g Release 2 thin driver (10.2.0.4) or later.
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
Related
I am trying to setup a REST API using Hibernate as my ORM Mapper. As IDE I am using IntelliJ. The project folder structure looks like this:
projectstructure
I setup the project with Glassfish like this instructions
The REST-API part works fine so I won't bother pasting all of that in here. To test the Hibernate functionality I wrote this class:
public class ArtistRepository {
public static void testHibernate(){
EntityManagerFactory factory = Persistence.createEntityManagerFactory("emf");
EntityManager manager = factory.createEntityManager();
Artist green = new Artist();
green.setName("TEST");
manager.getTransaction().begin();
manager.persist(green);
manager.getTransaction().commit();
}
}
The persistence.xml looks like this:
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="emf">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="hibernate.archive.autodetection" value="class, hbm" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
<property name="hibernate.connection.url"
value="jdbc:mysql://localhost:3306/database?autoReconnect=true" />
<property name="hibernate.connection.username" value="*****" />
<property name="hibernate.connection.password" value="*****" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.c3p0.min_size" value="5" />
<property name="hibernate.c3p0.max_size" value="10" />
<property name="hibernate.c3p0.timeout" value="300" />
<property name="hibernate.c3p0.max_statements" value="50" />
<property name="hibernate.c3p0.idle_test_period" value="300" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
</properties>
</persistence-unit>
</persistence>
When I request a REST resource using that method I get the following error:
<p>
<b>exception</b>
<pre>javax.servlet.ServletException: javax.persistence.PersistenceException: No Persistence provider for EntityManager named emf</pre>
</p>
<p>
<b>root cause</b>
<pre>javax.persistence.PersistenceException: No Persistence provider for EntityManager named emf</pre>
</p>
<p>
<b>note</b>
<u>The full stack traces of the exception and its root causes are available in the GlassFish Server Open Source Edition 5.0 logs.</u>
</p>
So obviousley the persistence.xml is in the wrong directory, but I have no clue where to put it.
I moved to Hibernate Persistence instead of open JPA persistence providerIMPL due to Jboss eap 6.4 open JPA issue earlier in persistence.xml it is mentioned as below for OPEN JPA
<property name="openjpa.TransactionMode" value="managed"></property>
<property name="openjpa.ConnectionRetainMode" value="always"/>
Now I changed to HibernatePersistence and added hibernatec3p0 properties instead of above property.
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>pac</jta-data-source>
<property name="hibernate.connection.provider_class"
value="org.hibernate.connection.C3P0ConnectionProvider" />
<property name="hibernate.c3p0.max_size" value="100" />
<property name="hibernate.c3p0.min_size" value="0" />
<property name="hibernate.c3p0.acquire_increment" value="1" />
<property name="hibernate.c3p0.idle_test_period" value="300" />
<property name="hibernate.c3p0.max_statements" value="0" />
<property name="hibernate.c3p0.timeout" value="100" />
Now my doubt is the above Hibernate c3p0 property solve OpenJPA transaction mode "managed" and connectionRetainmode "always".
Edit: I've update the post to reflect the questions in the comments below, but in summary, all of them are done but issue still exists
I'm trying to find a way to inject a Spring-managed EntityManager into my bean that handles the database update portion of a Spring Integration workflow.
For some reason, I keep getting a NullPointerException when trying to refer to the EM instance.
My setup is as follows:
#Component
public class BranchDeploymentUpdater {
#PersistenceContext(unitName = "MyPU")
private EntityManager em;
public File handleUpdate(File input) {
.....
String query = "some query";
TypedQuery<MyClass> typedQuery = em.CreateQuery(query, MyClass.class);
.....
}
}
My persistence.xml has been configured as follows:
<persistence-unit name="MyPU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://192.168.2.169:3306/MYDB" />
<property name="javax.persistence.jdbc.user" value="user" />
<property name="javax.persistence.jdbc.password" value="P#ssw0rd" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<!-- Connection Pooling -->
<property name="hibernate.connection.provider_class"
value="org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider" />
<property name="hibernate.c3p0.max_size" value="100" />
<property name="hibernate.c3p0.min_size" value="5" />
<property name="hibernate.c3p0.acquire_increment" value="5" />
<property name="hibernate.c3p0.idle_test_period" value="500" />
<property name="hibernate.c3p0.max_statements" value="50" />
<property name="hibernate.c3p0.timeout" value="10000" />
</properties>
</persistence-unit>
My component scan is declared at the springapp-servlet.xml document as follows and the class using EM is confirmed to be in the package declared:
<context:component-scan base-package="com.myapp.webapp.controller, com.myapp.integration" />
The NPE would occur at the em.CreateQuerystatement.
In this same project, I also have a MVC webapp which I'm injecting the EM into the controller class using the exact same way and it works.
Can anybody give any pointers to where I may be getting it wrong?
Currently, I'm working around this by instantiating a new EM every time the bean gets invoked but this is causing an out-of-connection error with MySQL if I pump in too many transactions.
Please note that I'm not using Spring Integration's DB adapters as I already have the JPA code for handling the database layer and would like to keep that layer.
Thanks
Wong
Thanks for all the comments. I was able to finally get it working by injecting an EntityManagerFactory instead, following the example provided in http://docs.spring.io/spring/docs/2.5.x/reference/orm.html#orm-jpa-tx
I think one key thing that I had left out previously is the line:
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
This really takes a load of my mind as I was having a helluva time with race conditions in the DB instantiating my own EMs.
I'm having troubles when generating sequences for an oracle databese running under the same instance than other one, with the same data structure. Here is a fragment of my persistence.xml where I define different schemas according to the persistence unit:
<persistence-unit name="oracle_development" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.archive.autodetection" value="class" />
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy" />
<property name="hibernate.connection.charSet" value="UTF-8" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="false" />
<property name="hibernate.connection.autocommit" value="false" />
<property name="hibernate.ejb.entitymanager_factory_name"
value="o11g" />
<property name="hibernate.default_schema" value="devdatabase"/>
</properties>
</persistence-unit>
<persistence-unit name="oracle_production" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.archive.autodetection" value="class" />
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy" />
<property name="hibernate.connection.charSet" value="UTF-8" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="false" />
<property name="hibernate.connection.autocommit" value="false" />
<property name="hibernate.ejb.entitymanager_factory_name"
value="o11g" />
<property name="hibernate.default_schema" value="proddatabase"/>
</properties>
</persistence-unit>
Well, the tables are generated perfectly, once the table names in creating commands include the default schema as qualifier. But sequences are not generated in the 'proddatabase' if they're already created on 'devdatabase', in example... Any help?
The hibernate.hbm2ddl.auto=”update” is convenient but less flexible if you plan on adding functions or executing some custom scripts.
So, the most flexible approach is to generate the DDL scripts with "org.hibernate.tool.ant.HibernateToolTask" and then use a component to execute the scripts on context startup. The destroy scripts are called when the Spring context is closed.
The second approach is much more flexible, especially if you want to mix JPA Entity Model with jOOQ Table Model.
Needless to say that this is only an Integration testing concern since for the production environment we use Flyway. So, you shouldn't rely on Hibernate for managing your database schema, because it's riskier, less flexible and it doesn't play well with CI and CD.
I am developing an application where persistence is done via JPA and Hibernate 4.2.3. everything is working normally the first moment.
However when you spend a certain time (in my case one day) application aprensenta the following error.
ERROR: Communications link failure
The last packet successfully received from the server was 259.217.434 milliseconds ago. The last packet sent successfully to the server was 0 milliseconds ago.
Abaixo deixo meu persistence.xml...
<persistence-unit name="amh_sys" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/amh_sys" />
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="root"/>
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="false" />
<property name="hibernate.use_sql_comments" value="false" />
<property name="hibernate.jdbc.wrap_result_sets" value="false" />
<property name="hibernate.hibernate.cache.use_query_cache" value="true" />
<property name="hibernate.c3p0.validate" value="true" />
</properties>
</persistence-unit>
I tried to configure using C3P0 connection pool, however had the same error ... Below configuration of C3P0.
<!-- Important -->
<property name="hibernate.connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider" />
<property name="hibernate.c3p0.max_size" value="100" />
<property name="hibernate.c3p0.min_size" value="0" />
<property name="hibernate.c3p0.acquire_increment" value="1" />
<property name="hibernate.c3p0.idle_test_period" value="300" />
<property name="hibernate.c3p0.max_statements" value="0" />
<property name="hibernate.c3p0.timeout" value="100" />
I can force the error by changing the date on your computer, because MySQL gets the same date as a reference. I can not solve this problem, I hope someone here had the same problem trying to share your solution applied.
Felipe.
The MySQL server will timeout the connect if it has been idle for too long. http://dev.mysql.com/doc/refman/5.0/en/gone-away.html You can do use a scheduled query within the timeout to keep the connect active or re-establish the connection by closing and re-creating the EntityManager