I have two applications to use the same database with same schema. Application A will read write the table A. Application B will read the table A only.
If I configured 2nd Level cache in both applications. Application B will not retrieve the updated value which application A updated the record in table A before.
I want to configure the same hibernate config to share the same cache with multiple applications (in this case, application B can get the updated value)
I read some stackoverflow but still not work for me.
I am using hibernate 5 and using Ehcache for cache management.
Any idea how I might implement this? May I have any reference?
Here are some hibernate Properties in my both applications
Sprint hibernate config:
<bean id="mySessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="annotatedClasses">
<list>
...
</list>
</property>
<property name="hibernateProperties">
<props>
<!-- Debug -->
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.hbm2ddl.auto">none</prop>
<!-- Level two caching -->
<prop key="hibernate.cache.provider_class">=net.sf.ehcache.hibernate.EhCacheProvider</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">false</prop>
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
<prop key="net.sf.ehcache.configurationResourceName">../conf/ehcache.xml</prop>
</property>
</bean>
ehcache.xml:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="true" monitoring="autodetect"
dynamicConfig="true" >
<diskStore path="java.io.tmpdir"/>
<!-- Default cache settings -->
<defaultCache
maxElementsInMemory="100000"
eternal="true"
timeToIdleSeconds="300"
timeToLiveSeconds="300"
overflowToDisk="false"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="300"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
You can consider using distributed cache like Hazelcast. In fact Hazelcast has built-in integration with Hibernate to easily plug in for second-level caching
Related
After upgrading Hibernate version from 4.3.9.Final to 5.0.2.Final, Tomcat Server start-up time has increased.
After debugging, I realized that hibernate takes too much time in adding mapping locations (*.hbm.xml files) in its metadata sources.
I have added mapping location in session factory using following code, and in my project there are around 1000 hbm.xml files.
<bean id="baseSessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.jdbc.fetch_size">300</prop>
<prop key="net.sf.ehcache.configurationResourceName">/ehcache.xml</prop>
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</prop>
</props>
</property>
<property name="dataSource" ref="dataSource" />
<property name="mappingLocations">
<list>
<value>classpath*:com/*/**/*.hbm.xml</value>
</list>
</property>
</bean>
While starting tomcat server, I debugged and fournd that in method
org.springframework.orm.hibernate5.LocalSessionFactoryBean.afterPropertiesSet
following for loop takes too much time to add all mapping locations in metadata sources object of configuration class.
if (this.mappingLocations != null) {
// Register given Hibernate mapping definitions, contained in resource files.
for (Resource resource : this.mappingLocations) {
sfb.addInputStream(resource.getInputStream());
}
}
Is there any solution to improve performance here? Anyone noticed such issue after upgrading to Hibernate-5?
Given two MySQL servers, one local, one remote.
Both have a database foobar containing a table bohica.
Local server has users 'myadmin'#'%' , 'myadmin'#'localhost' defined.
Remote server has users 'myadmin'#'%' , 'myadmin'#'localhost' and 'myadmin'#'my.domain.com' defined.
Privileges have been granted to all these users and privileges flushed.
Both servers are up.
From a command prompt window I can connect to both servers, ie
mysql --user=myadmin --password=mylocalpw
mysql --user=myadmin --password=myremotepw --host=my.domain.com
Both succeed, which proves that I can reach and log in to the remote server.
My java/maven/hibernate app has a context file
...
<bean id="databasePropertiesServerB"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<!--
<property name="location" value="classpath:databaseServerBlocal.properties" />
-->
<property name="location" value="classpath:databaseServerBliveadmin.properties" />
<property name="placeholderPrefix" value="$dbServerB{" />
<property name="placeholderSuffix" value="}" />
</bean>
<bean id="dataSourceServerB" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
<property name="uniqueResourceName" value="XADBMS_B" />
<property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
<property name="xaProperties">
<props>
<prop key="databaseName">foobar</prop>
<prop key="user">$dbServerB{hibernate.connection.username}</prop>
<prop key="password">$dbServerB{hibernate.connection.password}</prop>
</props>
</property>
<property name="poolSize"><value>20</value></property>
<property name="testQuery" value="SELECT 1" />
</bean>
<bean id="emfB" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="packagesToScan" value="com.mybiz.forms" />
<property name="dataSource" ref="dataSourceServerB" />
<property name="jpaDialect" ref="jpaHibernateDialect" />
<property name="jpaVendorAdapter" ref="jpaHibernateVendorAdapter" />
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">$dbServerB{hibernate.dialect}</prop>
<prop key="hibernate.connection.characterEncoding">$dbServerB{hibernate.connection.characterEncoding}</prop>
<prop key="hibernate.connection.driver_class">$dbServerB{hibernate.connection.driver_class}</prop>
<prop key="hibernate.connection.url">$dbServerB{hibernate.connection.url}</prop>
<prop key="hibernate.connection.release_mode">$dbServerB{hibernate.connection.release_mode}</prop>
<prop key="hibernate.cache.provider_class">$dbServerB{hibernate.cache.provider_class}</prop>
<prop key="hibernate.c3p0.min_size">$dbServerB{hibernate.c3p0.min_size}</prop>
<prop key="hibernate.c3p0.max_size">$dbServerB{hibernate.c3p0.max_size}</prop>
<prop key="hibernate.c3p0.timeout">$dbServerB{hibernate.c3p0.timeout}</prop>
<prop key="hibernate.c3p0.max_statements">$dbServerB{hibernate.c3p0.max_statements}</prop>
<prop key="hibernate.show_sql">$dbServerB{hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">$dbServerB{hibernate.format_sql}</prop>
<prop key="hibernate.hbm2ddl.auto">$dbServerB{hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.transaction.factory_class">com.atomikos.icatch.jta.hibernate3.AtomikosJTATransactionFactory</prop>
<prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup</prop>
</props>
</property>
</bean>
...
and properies files
databaseServerBliveadmin.properties
hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect
hibernate.connection.characterEncoding=UTF-8
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.url=jdbc:mysql://my.domain.com:3306/foobar
hibernate.connection.username=myadmin
hibernate.connection.password=myremotepw
hibernate.connection.release_mode=after_transaction
hibernate.cache.provider_class=org.hibernate.cache.NoCacheProvider
hibernate.c3p0.init_size=10
hibernate.c3p0.min_size=10
hibernate.c3p0.max_size=50
hibernate.c3p0.timeout=600
hibernate.c3p0.max_statements=50
hibernate.show_sql=false
hibernate.format_sql=true
hibernate.hbm2ddl.auto=create
and databaseServerBlocaladmin.properties
hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect
hibernate.connection.characterEncoding=UTF-8
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.url=jdbc:mysql://localhost:3306/foobar
hibernate.connection.username=myadmin
hibernate.connection.password=mylocalpw
hibernate.connection.release_mode=after_transaction
hibernate.cache.provider_class=org.hibernate.cache.NoCacheProvider
hibernate.c3p0.init_size=10
hibernate.c3p0.min_size=10
hibernate.c3p0.max_size=50
hibernate.c3p0.timeout=600
hibernate.c3p0.max_statements=50
hibernate.show_sql=false
hibernate.format_sql=true
hibernate.hbm2ddl.auto=update
Now it gets weird.
When I adjust the "location" property value in the "databasePropertiesServerB" bean to use databaseServerBlocal.properties,
the app can connect to the local server and do its thing as expected.
BUT (and you knew there a BUT coming...)
When I adjust the "location" property value in the "databasePropertiesServerB" bean to use databaseServerBliveadmin.properties,I get the dreaded
java.sql.SQLException: Access denied for user 'myadmin'#'localhost' (using password: YES)
errmsg. I can log in manually to the remote server which proves the username and password are correct.
I've been very careful to spell the username and password values correctly in the two .properties files - no trailing spaces, etc. So I'm stumped at this point. Any ideas?
TIA,
Still-learning Stev
complete answer appears here in a subsequent question
cannot achieve connectivity with MySQL db on remote machine
basically, everything about the hibernate properties file and the accounts and passwords on both instances of MySQL were all correct - the cause was not explicitly setting the xaProperties.server property in the Atomikos datasource bean that gets used by the entity manager factory bean - if not explicity set it defaults to 'localhost', which of course doesn't work on a remote machine because there it's trying to log in as xxxxx.%
Sneaky sneaky sneaky.
CASE CLOSED
Still-learning Steve
I have a spring app which do minimal operations with DB.
And I have a requirment that my application should run under the absence of DB(or when db is down).Below is my datasource configuration.
<bean id="dt31DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close" depends-on="systemPropertyInitializer"
p:driverClass="${dt31.driver_class}"
p:jdbcUrl="${dt31.url}"
p:user="${dt31.username}"
p:password="${dt31.password}"
p:idleConnectionTestPeriod="1000"
p:maxPoolSize="4"
p:minPoolSize="2"
p:maxIdleTime="2000"
p:unreturnedConnectionTimeout="600"
p:contextClassLoaderSource="library"
p:privilegeSpawnedThreads="true"
p:initialize=false
/>
<bean id="dt31SessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dt31DataSource"/>
<property name="packagesToScan" value="com.t22.dt31"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
${dt31.dialect}
</prop>
<prop key="hibernate.show_sql">
false
</prop>
<prop key="hibernate.hbm2ddl.auto">
update
</prop>
</props>
</property>
</bean>
I found a page in google,saying to use "initialize: false" in spring data source configuration.But I am using "ComboPooledDataSource" datasource which does not have this property.Is there any other way to achieve this ?
The application service layer can operate with two DAO layers (file system and database), so when the DB is down you catch the connection acquire exception and switch to the file system instead.
Having two sources of truth is going to make it difficult to preserve consistency across two different data sources, especially if one resource is not available.
When both resources are available you can use XADisk and Bitronix for XADataSource and JTA transaction management.
I am migrating an application from
Spring 3.0.5 + JPA 2.0
to
Spring 4 + JPA (Hibernate 4)
I have followed the migration guide : https://github.com/spring-projects/spring-framework/wiki/Migrating-from-earlier-versions-of-the-spring-framework.
The application is using a JTA transaction manager : a Jencks / GeronimoPlatformTransactionManager (because of transactions distributed on datasources and ESB).
The Spring / JPA configuration is :
<bean id="rduEntityManagerFactory" class="ch.vd.dsas.rdu.repository.crud.service.ExtendedLocalContainerEntityManagerFactoryBean"
depends-on="rduTransactionManagerLocator,jGroupsCacheManagerPeerProviderFactoryLocator">
<property name="persistenceUnitName" value="rduPersistenceUnit" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="${rdu.jpa.database}" />
</bean>
</property>
<property name="persistenceUnitPostProcessors">
<bean class="ch.vd.dsas.rdu.commons.tx.spring.JtaPersistenceUnitPostProcessor">
<property name="jtaDataSource" ref="rduDataSource" />
</bean>
</property>
<property name="jpaProperties" ref="jpaProperties"/>
</bean>
<util:properties id="jpaProperties">
<prop key="javax.persistence.transactionType">JTA</prop>
<prop key="javax.persistence.validation.mode">CALLBACK</prop>
<prop key="hibernate.hbm2ddl.auto">${rdu.jpa.hbm2ddl.auto}</prop>
<prop key="hibernate.current_session_context_class">jta</prop>
<!-- Transaction properties -->
<prop key="hibernate.transaction.jta.platform">ch.vd.dsas.rdu.ref.transaction.jencks.JencksTransactionManagerLookup</prop>
<prop key="hibernate.transaction.manager_lookup_class">ch.vd.dsas.rdu.transaction.jencks.JencksTransactionManagerLookup</prop>
<prop key="hibernate.default_schema">${rdu.datasource.schemaMetier}</prop>
<!-- Debug properties -->
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.show_sql">true</prop>
<!-- Cache properties -->
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.region.factory_class">net.sf.ehcache.hibernate.ReplicatedSingletonEhCacheRegionFactory</prop>
<prop key="hibernate.cache.cluster_name">${rdu.hibernate.cache.jgroups.cluster.name}</prop>
<prop key="net.sf.ehcache.configurationResourceName">/hibernate-ehcache.xml</prop>
</util:properties>
Transactions are annotation driven :
<tx:annotation-driven transaction-manager="rduJtaTransactionManager" />
The transaction manager is declared like that :
<!-- From Jencks org.jencks:jencks:2.2 -->
<bean id="rduJencksTransactionManager" class="org.jencks.factory.TransactionManagerFactoryBean" />
<bean id="rduJtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<qualifier value="rdu" />
<property name="transactionManager" ref="rduJencksTransactionManager" />
<property name="userTransaction" ref="rduJencksTransactionManager" />
</bean>
<bean id="rduTransactionManagerLocator" class="ch.vd.dsas.rdu.transaction.jencks.TransactionManagerLocator" factory-method="getInstance">
<property name="transactionManager" ref="rduJencksTransactionManager"/>
</bean>
The application is starting and accessing data and displaying it.
However no insert / update are performed.
If I change data and submit the change the application receives the change but the data does not get flushed to the database.
I have activated logs and I see the transaction :
rdu 2015-06-18 20:28:01,817 [ http-8080-1] DEBUG [ o.s.t.j.JtaTransactionManager] Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; 'rdu'
rdu 2015-06-18 20:28:01,817 [ http-8080-1] DEBUG [ o.s.t.j.JtaTransactionManager] Participating in existing transaction
rdu 2015-06-18 20:28:01,823 [ http-8080-1] DEBUG [ o.s.t.j.JtaTransactionManager] Initiating transaction commit
But nothing is sent to the database.
If I intercept the execution through debugging and manually flush the Hibernate session, the data gets updated.
It seems the JPA / Hibernate session is not coordinated with the transaction.
I can't figure out what is missing in the configuration and why the session is not flushed automatically.
Hope you can help me with this issue.
Best regards,
Eric
The problem is due to this property:
<prop key="hibernate.transaction.jta.platform">ch.vd.dsas.rdu.ref.transaction.jencks.JencksTransactionManagerLookup</prop>
The hibernate.transaction.jta.platform property is not the same with hibernate.transaction.manager_lookup_class and it should point to an AbstractJtaPlatform implementation:
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform"/>
I currently use spring for depency injection. Hibernate uses a postgres dialect for the normal run, but I want to use HSQL for the DBUnitils Databank-Testing.
My Spring-Configuration contains this:
<!-- Hibernate session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="use_outer_join">${hibernate.use_outer_join}</prop>
<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
<prop key="hibernate.cache.provider_class">${hibernate.cache.provider}</prop>
<prop key="hibernate.connection.pool_size">10</prop>
<prop key="hibernate.jdbc.batch_size">1000</prop>
<prop key="hibernate.bytecode.use_reflection_optimizer">true</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<value>de.dbruhn.relations.model.Relation</value>
<value>de.dbruhn.relations.model.RelationData</value>
<value>de.dbruhn.relations.model.RObject</value>
<value>de.dbruhn.relations.model.Type</value>
</list>
</property>
<property name="schemaUpdate" value="${hibernate.schemaUpdate}"/>
</bean>
The fields get replaced by maven resource-filtering.
The Spring-Configruation for DBUnitils contains this:
<bean id="dataSource" class="org.unitils.database.UnitilsDataSourceFactoryBean"/>
</beans>
and so overrides the dataSource from my run configuration with the UnitilsDataSource.
The Problem: I cant run the Tests using Postgres-Dialect against the HSQL-Test-Database because some commands dont work.
The only solution which came to my mind: Switching the resource-filter in maven, but I have to do this by hand (by provining a "-P TEST" on every maven call). So isn't there a possibilty to override the hibernate.dialect?
Thanks!
You normally don't need to specify the dialect at all, Hibernate will figure it out by looking at the underlying datasource. You only need to specify the dialect if you want to force Hibernate to use a specific one.
In your case, you should just be able to remove the dialect property completely, and it should work in postgres and hsql without config modification.
You should possibly look at using the PropertyPlaceHolderConfigurer in spring to change the config. That way you need only supply a different config file for the different environments, the spring xml stays the same.
And you can load the config file like this.