How to qualify sequence names in Hibernate? - java

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.

Related

Exception in JPA Persistance

I have question...I Have two JAR file, which have similar code, and one is in English and second for Deutch...I have two DB (for EN a DE), but I want to have same table names. If I start this, I have two definitions for same table...I want to keep the table same for the JAR, which will change. But it's enough for me to load one of this two. How can I do it? My app is bigger...
I don't want the modification of one table definition to be written to both tables.
Some advice? In persistance you can see some solve? Thanks
<jar-file>FA_DE-MLA-1.0.jar</jar-file>
<jar-file>FA_EN-MLA-1.0.jar</jar-file>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.enable_lazy_load_no_trans" value="true"/>
<property name="javax.persistence.validation.mode" value="none" />
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
<property name="hibernate.show_sql" value="false"/>
<property name="hibernate.format_sql" value="false"/>
<property name="hibernate.create_empty_composites.enabled" value="true"/>
</properties>

JPA does not honours caching while creating entity manager factory dynamically

I am using hibernate 4.2 and working on J2ee6 with tomee 1.7.4 . I need to write multi-tenant code, which can connect to various databases on demand. I tried doing this by creating multiple persistence units in persistence.xml, but during server startup tomee tries to validate connection to all persistence units(all of them might not be available during testing).
I tried to find some setting that tells tomee to skip validation of the connections at startup, but couldn't find one. So instead of creating entitymanager from persistence unit, I started using the function
javax.persistence.Persistence.createEntityManagerFactory(String persistenceUnitName, Map properties)
and my persistence xml did not had any properties. This helped me solve this problem, but my caching stopped working when i moved to this model, it was working previously.
Can any one suggest some way in which i can ask tomee to skip validating persistence units at startup, or i can enable caching in the other way that i found.
My previous persistence.xml looked like
<?xml version="1.0" encoding="UTF-8" ?><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_2_0.xsd"
version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="localDB" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<properties>
<property name="hibernate.connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="false" />
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/xxxxxx?autoReconnect=true" />
<property name="hibernate.connection.username" value="xxxxx" />
<property name="hibernate.connection.password" value="xxxxx" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.c3p0.acquire_increment" value="1"/>
<property name="hibernate.c3p0.max_size" value="40"/>
<!-- it must be set to LESS than the wait_timout setting for the mysql server (this setting defaults to 28800 secs (8 hours)) -->
<property name="hibernate.c3p0.idle_test_period" value="28680" />
<property name="hibernate.c3p0.preferredTestQuery" value="select 1;" />
<property name="hibernate.c3p0.timeout" value="60000"/>
<property name="hibernate.connection.zeroDateTimeBehavior" value="convertToNull"/>
<property name="hibernate.c3p0.debugUnreturnedConnectionStackTraces " value="true"/>
<property name="debugUnreturnedConnectionStackTraces " value="true"/>
<property name="hibernate.cache.use_second_level_cache" value="true" />
<property name="hibernate.cache.use_query_cache" value="true" />
<property name="hibernate.cache.region.factory_class" value="com.mc.hibernate.memcached.MemcachedRegionFactory" />
<property name="hibernate.memcached.operationTimeout" value = "40000"/>
<property name="hibernate.memcached.connectionFactory" value = "KetamaConnectionFactory"/>
<property name="hibernate.memcached.hashAlgorithm" value = "HashAlgorithm.FNV1_64_HASH"/>
<property name="hibernate.memcached.servers" value = "xxxxx:xxxx"/>
<property name="hibernate.cache.region_prefix" value=""/>
</properties>
</persistence-unit>
<persistence-unit name="production" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<properties>
<property name="hibernate.connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="false" />
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
<property name="hibernate.connection.url" value="jdbc:mysql://xxxxx:3306/thewalkindb?autoReconnect=true" />
<property name="hibernate.connection.username" value="xxxx" />
<property name="hibernate.connection.password" value="xxxxx" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.c3p0.acquire_increment" value="1"/>
<property name="hibernate.c3p0.max_size" value="15"/>
<!-- it must be set to LESS than the wait_timout setting for the mysql server (this setting defaults to 28800 secs (8 hours)) -->
<property name="hibernate.c3p0.idle_test_period" value="28680" />
<property name="hibernate.c3p0.preferredTestQuery" value="select 1;" />
<property name="hibernate.c3p0.timeout" value="60000"/>
<property name="hibernate.connection.zeroDateTimeBehavior" value="convertToNull"/>
<property name="hibernate.c3p0.debugUnreturnedConnectionStackTraces " value="true"/>
<property name="debugUnreturnedConnectionStackTraces " value="true"/>
<property name="hibernate.cache.use_second_level_cache" value="true" />
<property name="hibernate.cache.use_query_cache" value="true" />
<property name="hibernate.cache.region.factory_class" value="com.mc.hibernate.memcached.MemcachedRegionFactory" />
<property name="hibernate.memcached.operationTimeout" value = "40000"/>
<property name="hibernate.memcached.connectionFactory" value = "KetamaConnectionFactory"/>
<property name="hibernate.memcached.hashAlgorithm" value = "HashAlgorithm.FNV1_64_HASH"/>
<property name="hibernate.memcached.servers" value = "xxxxxxxx"/>
<property name="hibernate.cache.region_prefix" value=""/>
</properties>
</persistence-unit>
this works with caching , but it doesnot gives me flexibility to skip validation at tomee startup
My new persistence xml which does not honours caching, but allows me the flexibility is as follows
<?xml version="1.0" encoding="UTF-8" ?>
<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_2_0.xsd"
version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="localDB" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<properties></properties>
</persistence-unit>
<persistence-unit name="production" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<properties>
</properties>
</persistence-unit>
I am populating all the properties in a map and calling the function
javax.persistence.Persistence.createEntityManagerFactory(String persistenceUnitName, Map properties), but somehow it does not honours caching.
I don't get the link between validation and caching. If you do a facade to the entity manager tenant aware you just have caching per entity manager which means you will not check local cache for production persistence unit.
If you want a single entity manager - =you'll get a single JPA cache in this mode which will merge local and production - you can use dynamic routing: http://tomee.apache.org/examples-trunk/dynamic-datasource-routing/README.html instead of dynamic persistence units.

Externalize dynamic properties in persistence.xml

We are using the bellow properties in our persistence.xml file.
<properties>
<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.driver.OracleDriver" />
<property name="javax.persistence.jdbc.dialect" value="org.hibernate.dialect.OracleDialect" />
<property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:#XYZDB01:78111:TATAD1" />
<property name="javax.persistence.jdbc.user" value="admin" />
<property name="javax.persistence.jdbc.password" value="admin#123" />
<property name="javax.persistence.jdbc.Schema" value="CSMVC" />
</properties>
But I want to externalize the dynamic properties from persistence.xml something like bellow.
<properties>
<property name="javax.persistence.jdbc.driver" value="${db.driver}" />
<property name="javax.persistence.jdbc.dialect" value="${db.dialect}" />
<property name="javax.persistence.jdbc.url" value="${db.url}" />
<property name="javax.persistence.jdbc.user" value="${db.user}" />
<property name="javax.persistence.jdbc.password" value="${db.password}" />
<property name="javax.persistence.jdbc.Schema" value="${db.schema}" />
</properties>
Note: We are using openJpa as the JPA provider.
Normally, you would define your datasource in your container and have JPA look it up via JNDI. Are you running JPA in Spring/TomEE/Tomcat/Wildfly/Liberty or anything else?

Best way to create schema in embedded HSQL database

I'm currently using the following setup to create a schema in an embedded database before running my tests against it
In my application context
<jdbc:embedded-database id="dataSource" type="HSQL">
<jdbc:script location="classpath:createSchema.sql" />
</jdbc:embedded-database>
createSchema.sql
create schema ST_TEST AUTHORIZATION DBA;
hibernate properties
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
<property name="hibernate.default_schema" value="ST_TEST"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.use_sql_comments" value="true" />
<property name="hibernate.cache.use_second_level_cache" value="false" />
</properties>
My question is is this the best way to do this. Or can i use a different schema name in my properties? or set the schema name in the jdbc:embedded-database element
By default HSQL creates a schema called PUBLIC. source: HSQL documentation
Seeing as the schema name is never seen in the tests (named queries/entity manager to do the interactions) you can change the hibernate properties to use this PUBLIC schema
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
<property name="hibernate.default_schema" value="PUBLIC"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
</properties>
OR
just leave out the default_schema from the properties list and it uses PUBLIC anyway
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
</properties>
You can use this code in your Base Testing class, and call it using #BeforeClass annotation (for Junit). I do it like this.
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
builder = builder.setType(EmbeddedDatabaseType.HSQL).addScript(
"createSchema.sql");
builder.setName("MyDatabase");
EmbeddedDatabase db = builder.build();

Hibernate > CLOB > Oracle :(

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

Categories