Best way to create schema in embedded HSQL database - java

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();

Related

Configure HikariCP + Hibernate + GuicePersist(JPA) at Runtime

I have a java8 desktop app using GuicePersist, Hibernate, and HikariCP to communicate with a Postgres DB. I've had success getting my app to send/receive data to the DB using this META-INF/persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<!-- A JPA Persistence Unit -->
<persistence-unit name="myJPAunit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>com.123fakestreet.bogus.tomb.impl.postgres.model.movies</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<!-- SQL stuff -->
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL9Dialect" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="validate" />
<!-- hikari CP -->
<property name="hibernate.connection.provider_class" value="org.hibernate.hikaricp.internal.HikariCPConnectionProvider" />
<property name="hibernate.hikari.minimumIdle" value="20" />
<property name="hibernate.hikari.maximumPoolSize" value="100" />
<property name="hibernate.hikari.idleTimeout" value="30000" />
<property name="hibernate.hikari.dataSourceClassName" value="org.postgresql.ds.PGSimpleDataSource" />
<property name="hibernate.hikari.dataSource.url" value="jdbc:postgresql://192.168.100.75:5432/mpDb" />
<property name="hibernate.hikari.username" value="cowboy" />
<property name="hibernate.hikari.password" value="bebop" />
<!-- Disable the second-level cache -->
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
<!-- Default is false for backwards compatibility. Should be used on all new projects -->
<property name="hibernate.id.new_generator_mappings" value="true"/>
</properties>
</persistence-unit>
</persistence>
The tricky part is configuring my Guice JpaPersistModule at runtime.
From what I can tell, I should be able to override properties in my META-INF/persistence.xml file by setting properties in a Map object, like this:
Map<String, String> properties = new HashMap<>();
properties.put("myJPAunit.hibernate.hikari.dataSource.url", "jdbc:postgresql://192.168.100.75:5432/mpDb");
properties.put("myJPAunit.hibernate.hikari.dataSource.user", "cowboy");
properties.put("myJPAunit.hibernate.hikari.dataSource.password", "bebop");
then jpaModule.properties(properties), and then pass this all to GuicePersist.
I've tried some different combinations of property names in the Map but so far I've had no luck. I've also looked at the pgsimpledatasource docs and the hikariCP docs regarding this topic, but still my datasource properties are not getting set.
Can somebody help? Thanks a bunch.
Try removing the persistence-unit name from the JPA properties, so instead of:
Map<String, String> properties = new HashMap<>();
properties.put("myJPAunit.hibernate.hikari.dataSource.url", "jdbc:postgresql://192.168.100.75:5432/mpDb");
properties.put( + "myJPAunit.hibernate.hikari.dataSource.user", "cowboy");
properties.put( + "myJPAunit.hibernate.hikari.dataSource.password", "bebop");
you should have this:
Map<String, String> properties = new HashMap<>();
properties.put("hibernate.hikari.dataSource.url", "jdbc:postgresql://192.168.100.75:5432/mpDb");
properties.put("hibernate.hikari.dataSource.user", "cowboy");
properties.put("hibernate.hikari.dataSource.password", "bebop");

How to qualify sequence names in Hibernate?

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.

Spring + Websphere 8.5: Unable to lookup JNDI name [java:comp/websphere/ExtendedJTATransaction]

There is a Websphere AS 8.5 where runs XA Datasource. Also there is a Spring application which must work in this environment and connect to the datasource. An application context is loaded by a servlet and the application uses RmiExporters to provide RMI access to some services (which are shared in the separate thread) and all DAOs' methods are marked with #Transactional.
If I try to write something to the database from the main thread (e.g. during initialization of any class), it works properly. But if I try to write (or read with HQL SELECT-query) something via RMI invokation I see an exception:
org.hibernate.service.jndi.JndiException: Unable to lookup JNDI name [java:comp/websphere/ExtendedJTATransaction]
at org.hibernate.service.jndi.internal.JndiServiceImpl.locate(JndiServiceImpl.java:68)
at org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform$TransactionManagerAdapter$TransactionAdapter.<init>(WebSphereExtendedJtaPlatform.java:156)
at org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform$TransactionManagerAdapter$TransactionAdapter.<init>(WebSphereExtendedJtaPlatform.java:152)
at org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform$TransactionManagerAdapter.getTransaction(WebSphereExtendedJtaPlatform.java:124)
at org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform$TransactionManagerAdapter.getStatus(WebSphereExtendedJtaPlatform.java:119)
at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.getStatus(JtaStatusHelper.java:73)
at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.isActive(JtaStatusHelper.java:115)
at org.hibernate.service.jta.platform.internal.TransactionManagerBasedSynchronizationStrategy.canRegisterSynchronization(TransactionManagerBasedSynchronizationStrategy.java:56)
at org.hibernate.service.jta.platform.internal.AbstractJtaPlatform.canRegisterSynchronization(AbstractJtaPlatform.java:148)
at org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl.attemptToRegisterJtaSync(TransactionCoordinatorImpl.java:240)
at org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl.pulse(TransactionCoordinatorImpl.java:268)
at org.hibernate.ejb.AbstractEntityManagerImpl.joinTransaction(AbstractEntityManagerImpl.java:1202)
at org.hibernate.ejb.AbstractEntityManagerImpl.postInit(AbstractEntityManagerImpl.java:178)
at org.hibernate.ejb.EntityManagerImpl.<init>(EntityManagerImpl.java:89)
at org.hibernate.ejb.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:179)
at org.hibernate.ejb.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:174)
at com.ibm.ws.jpa.management.JPAEMFactory.createEntityManager(JPAEMFactory.java:297)
at org.springframework.orm.jpa.EntityManagerFactoryUtils.doGetTransactionalEntityManager(EntityManagerFactoryUtils.java:202)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:211)
at com.sun.proxy.$Proxy414.persist(Unknown Source)
Actual configuration is the following:
persistence unit in the persistence.xml:
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/oracledatasource</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
<property name="hibernate.archive.autodetection" value="class" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="true" />
<property name="connection.pool.size" value="5" />
<property name="current_session_context_class" value="managed" />
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory" />
<property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory" />
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup" />
<property name="hibernate.cache.use_second_level_cache" value="false" />
<property name="hibernate.cache.use_query_cache" value="false" />
<property name="hibernate.generate_statistics" value="true" />
<property name="hibernate.enable_lazy_load_no_trans" value="true" />
</properties>
Spring configuration looks like this:
<tx:jta-transaction-manager />
<tx:annotation-driven />
<bean id="transactionManager" class="org.springframework.transaction.jta.WebSphereUowTransactionManager" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
<property name="persistenceUnits">
<map>
<entry key="pu1" value="persistence/pu1" />
</map>
</property>
</bean>
<jee:jndi-lookup id="entityManagerFactory" jndi-name="persistence/pu1"/>
What can I try to fix this problem?
The actual solution was to use JPATransactionManager of Spring with LOCAL_RESOURCE persistence unit.

default table prefix in persistence

How to configure default table prefix in persistence configuration file. I'm using Spring's default configuration as follows:
<persistence-unit name="primary">
<jta-data-source>java:jboss/datasources/MysqlDS</jta-data-source>
<properties>
<property name="jboss.entity.manager.factory.jndi.name" value="java:jboss/spring-quickstart/persistence" />
<!-- Properties for Hibernate -->
<property name="hibernate.hbm2ddl.auto" value="create" />
<property name="hibernate.show_sql" value="false" />
</properties>
thanks
Looks like this SO question has the answer you seek.
Looks like what G. Bach refers to only allows you to change "metadata tables"?

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