Configure HikariCP + Hibernate + GuicePersist(JPA) at Runtime - java

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

Related

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.

OpenJPA Configuration in WAS 7.0.0.25

I am looking at the performance optimization of Open JPA for my WAS 7.0.0.25 server. I enabled OpenJPA trace from WAS console to understand what properties are taken for caching.
There is no openjpa.= type entry in my persistance.xml. But I can see entries in the trace.log as below:
openjpa.IgnoreChanges: false
openjpa.FlushBeforeQueries: 0
openjpa.ConnectionRetainMode: 0
But i could not find the configuration that sets these properties so that I can play around with them.
Can anyone guide me where I can find these values coming from the Open JPA provided by WAS 7?
Accordingly to the documentation you should add this line to your persistence.xml:
<property name="openjpa.Log" value="DefaultLevel=WARN, Runtime=INFO, Tool=INFO, SQL=TRACE"/>
http://openjpa.apache.org/builds/1.0.2/apache-openjpa-1.0.2/docs/manual/ref_guide_logging_openjpa.html
ADDED
If you add those keys in your persistence.xml, probably the default values will be overridden.
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
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">
<persistence-unit name="...">
<properties>
<property name="openjpa.jdbc.DBDictionary" value="oracle" />
<property name="openjpa.Log" value="DefaultLevel=WARN, Runtime=INFO, Tool=INFO, SQL=TRACE"/>
<property name="openjpa.AutoDetach" value="close" />
<property name="openjpa.DetachState" value="loaded" />
<property name="openjpa.DataCache" value="false" />
<property name="openjpa.Optimistic" value="true" />
<property name="openjpa.Multithreaded" value="true" />
<property name="openjpa.TransactionMode" value="managed" />
<property name="openjpa.ConnectionFactoryMode" value="managed" />
<property name="openjpa.NontransactionalRead" value="true" />
<property name="openjpa.RestoreState" value="all" />
<property name="openjpa.ManagedRuntime" value="auto" />
</properties>
</persistence-unit>
</persistence>
Xhings -
If you are looking for default configuration values, you should start by looking at the user manual. That beings said, the only property that I would recommend (from a performance point of view) to change is openjpa.ConnectionRetainMode. Setting that property to always has shown some performance impact.

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

PersistenceProvider createEntityManagerFactory returns null in Eclipse Plugin

I created a standalone app to access my database (either mssql or h2)
i created a helper class which connects to my server by passing the connection details.
all fine and works as it is supposed to be.
now i move my code to an Eclipse Plugin (->OSGi)
first i ran into a Driver Not Found Error, but i fixed this with passing my ClassLoader to the PersistenceProvider.
now i got the next problem, which i am not able to resolve:
the PersistenceProvider returns null, when i call createEntityManagerFactory passing the persistence unit name and my map.
it does not throw any exceptions...simply returns null
so i guess the driver is found...
as the standalone application is working, it can't be the persistence.xml either...
any ideas?
here my persistence.xml
<?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="EclipseLinkTest" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<!-- <mapping-file>META-INF/contact-orm.xml</mapping-file> -->
<properties>
<!-- <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" /> -->
<!-- <property name="javax.persistence.jdbc.url" value="jdbc:h2:D:/JAVA/Final/lumo.osgi.service.eclipselink.impl/db/embedded.db" /> -->
<!-- <property name="javax.persistence.jdbc.user" value="admin" /> -->
<!-- <property name="javax.persistence.jdbc.password" value="admin" /> -->
<!-- <property name="javax.persistence.jdbc.driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" /> -->
<!-- <property name="javax.persistence.jdbc.url" value="jdbc:sqlserver://dbserverIP:1433;DatabaseName=testsystem" /> -->
<!-- <property name="javax.persistence.jdbc.user" value="editor" /> -->
<!-- <property name="javax.persistence.jdbc.password" value="editorpwd" /> -->
<!-- EclipseLink should create the database schema automatically -->
<!-- <property name="eclipselink.ddl-generation" value="drop-and-create-tables" /> -->
<!-- <property name="eclipselink.ddl-generation" value="create-tables" /> -->
<!-- <property name="eclipselink.ddl-generation.output-mode" value="database" /> -->
<!-- <property name="eclipselink.weaving" value="true"/> -->
<property name="eclipselink.logging.level" value="WARNING"/>
</properties>
</persistence-unit>
</persistence>
and this is the code to get the configuration (application is the main class - so its class loader got information about everything in my target definition)
public Properties getEmbeddedConfiguration(String path, String database,
String login, String password) {
Properties props = new Properties();
// this one is for getting started in OSGi & JPA
// No suitable driver found for jdbc:h2:file:C:\temp\Thumbs.db;IFEXISTS=TRUE
// props.put(PersistenceUnitProperties.CLASSLOADER,
// EclipseLinkServiceImpl.class.getClassLoader());
// this fixes the driver not found but leaves a nullpointer
props.put(PersistenceUnitProperties.CLASSLOADER,
Application.class.getClassLoader());
String connectionString = String.format(
"jdbc:h2:file:%s%s;IFEXISTS=TRUE", path, database);
props.put("javax.persistence.jdbc.driver", "org.h2.Driver");
props.put("javax.persistence.jdbc.url", connectionString);
props.put("javax.persistence.jdbc.user", login);
props.put("javax.persistence.jdbc.password", password);
props.put("eclipselink.target-database",
"org.eclipse.persistence.platform.database.H2Platform");
props.put("eclipselink.ddl-generation", "drop-and-create-tables");
props.put("eclipselink.ddl-generation.output-mode", "database");
return props;
}
and last but not least the create part
PersistenceProvider p = new PersistenceProvider();
factory = p.createEntityManagerFactory(PERSISTENCE_UNIT_NAME,
getEmbeddedConfiguration(folder, database, username, pwd));
System.out.println("factory: " + factory);
em = factory.createEntityManager();
To get JPA running in OSGi take a look at the Gemini project

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

Categories