Configure Query Cache in Hibernate4 - java

I'm trying enable query cache in our application. As per the documentation I have given
hibernate.cache.use_query_cache as true and givent setCacheable() in my queries. But I'm getting below exception.
org.hibernate.cache.NoCacheRegionFactoryAvailableException: Second-level cache is used in the application, but property hibernate.cache.region.factory_class is not given, please either disable second level cache or set correct region factory class name to property hibernate.cache.region.factory_class (and make sure the second level cache provider, hibernate-infinispan, for example, is available in the classpath).
Should I specify cache region for query cache, I'm using Hibernate 4. Please help me in this regard

Use Following for hibernate 4.
I am using this with hibernate 4.3
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.use_query_cache">true</property>

Related

Can't achieve working with p6Spy

I've tried two methods for adding p6Spy feature to my spring used project.
Route I,
http://templth.blogspot.com.tr/2004/11/integrate-p6spy-with-spring.html
I changed my driver with com.p6spy.engine.spy.P6SpyDriver and added realdriver realdriver=com.ibm.db2.jcc.DB2Driver into spy.properties file.
But somehow my realdriver is being registered before p6spy driver com.ibm.db2.jcc.DB2Driver is a real driver in spy.properties, but it has been loaded before p6spy. p6spy will not wrap these connections.Either prevent the driver from loading, or try setting 'deregisterdrivers' to true in spy.properties
Using :p6spy: prefix doesn't work for me. It says can't establish connection with that url.
So,I chose setting this deregisterdrivers=true in property file.
This time I get sql in log file but can't execute sqls. I'm able to execute sql in another sql editor. It seemed real connection went and a dummy one came.
Route II,
We use spring. So I've tried this method. Giving datasource explicitly to p6Spy. But this time spring complained of multiple java.sql.DataSource instance. Both com.firm.BasicDataFill and com.p6spy.engine.spy.P6DataSource implements DataSource. Spring can't obtain a singleton.
http://templth.blogspot.com.tr/2004/11/integrate-p6spy-with-spring.html
<bean id="dataSource" lazy-init="true"
class="com.firm.BasicDataFill">
<property name="driverClassName" value="${database.connection.driver_class}" />
<property name="username" value="${database.connection.username}" />
<property name="password" value="${database.connection.password}" />
<property name="url" value="${database.connection.url}" />
...
<property name="accessToUnderlyingConnectionAllowed" value="true" />
</bean>
<!-- bean id="myDataSource" class="com.p6spy.engine.spy.P6DataSource">
<constructor-arg>
<ref local="dataSource"/>
</constructor-arg>
</bean-->
Finally, I discovered p6spy v1.3 and 2.4.1 settings vary. Do you have any suggestion for a spring based application.
I would recommend starting with the latest version of P6Spy 2.x. You should also REPLACE your spy.properties file with the default version for 2.X which is documented here. Depending on your application server, you might need to set the 'realdriver' setting in spy.properties to include 'com.ibm.db2.jcc.DB2Driver'. However, this is only needed when you are using an application server that prevents the automatic registration of JDBC Drivers.
To use P6Spy with Spring, the easiest method is to wrap your current data source bean with P6SpyDataSource as discussed here. The example in that answer shows a JNDI data source being wrapped but it can be used to wrap any data source. Note: If you are wrapping the data source is P6SpyDataSource, you do NOT need to modify the JDBC URL.
If you continue to have problems, please add a bit more information to your question. The following information would be helpful in troubleshooting:
The version of P6Spy being used
The contents of spy.properties
The definition of your datasource (including app server config if
using JNDI)
The type of app server and version being used
Stacktrace containing whatever error you might have received.
Have a look at Log4jdbc it'll do the job https://code.google.com/p/log4jdbc/

Configuring Infinispan as remote second level cache for Hibernate

As per Infinispan documentation the following settings make up setting infinispan as a L2 Cache provider for Entities
<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="org.hibernate.cache.infinispan.InfinispanRegionFactory"/>
Then further one can annotate Entities with #javax.persistence.Cacheable to make them candidate for L2 cache.
My question is how to make this a remote cache ?
Infinispan 2LC implementation for remote cache does not exist. You could maybe configure the embedded caches used for Infinispan 2LC with a remote cache store which talks to one or multiple Infinispan Servers. Please note that this has not been tested and there's no guarantees that it'll work as expected due to the peculiarities and the optimizations done by the embedded Infinispan 2LC implementation.

How do I use a replica set seed list with Hibernate and MongoDB

I have an application that is written in Java and was written before by someone else before I got control of it. We are using MongoDB with a replica set. I know that in order to use the replica set properly, you need to pass the driver a "seed list" of all servers associated with the replica set in order for it to choose the primary.
The problem is that the application is using Hibernate to connect to MongoDB. Is there a way to specify the seed list inside the Hibernate xml configuration file? Below is a sample of what we have configured in the application.
<hibernate-configuration>
<session-factory>
<property name="hibernate.ogm.datastore.provider">MONGODB</property>
<property name="dialect">org.hibernate.ogm.dialect.mongodb.MongoDBDialect</property>
<property name="hibernate.ogm.mongodb.database">databasename</property>
<property name="hibernate.ogm.mongodb.host">192.168.1.10</property>
<property name="hibernate.ogm.mongodb.port">27017</property>
<mapping resource="mongodb.hbm.xml" />
</session-factory>
</hibernate-configuration>
I tried to find documentation on the list of properties for this configuration and didn't see anything about specifying multiple hosts for a seed list; hibernate.ogm.mongodb.host is the only thing I could find and as far as I know, it only supports 1 host.
Any ideas on how I can make the current application work with a replica set seed list using hibernate?
The latest versions of Hibernate OGM support this via the property:
hibernate.ogm.datastore.host
Here's an example of a valid value:
www.example.com, www2.example.com:123, 192.0.2.1, 192.0.2.2:123, 2001:db8::ff00:42:8329, [2001:db8::ff00:42:8329]:123
The default value is 127.0.0.1:27017. If left undefined, the default port is 27017.
There are more details in the official documentation

web application structure hierarcy problem

Below an illustration of my project hierarchy
(source: yfrog.com)
When i try to connect my file_name.java file to hibernate i'm getting these errors
Exception in thread "main" org.hibernate.HibernateException: Could not instantiate cache implementation
at org.hibernate.cache.CacheFactory.createCache(CacheFactory.java:64)
at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:214)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1218)
at net.pkg.dao.FirstExample.main(FirstExample.java:17)
Caused by: org.hibernate.cache.NoCachingEnabledException: Second-level cache is not enabled for usage [hibernate.cache.use_second_level_cache | hibernate.cache.use_query_cache]
at org.hibernate.cache.NoCacheProvider.buildCache(NoCacheProvider.java:21)
at org.hibernate.cache.CacheFactory.createCache(CacheFactory.java:61)
the problem has something to do with my hibernate.cfg.xml... but I'm unable to resolve it. Any ideas?
I suspect that you are using either #Cacheable or #Cache on your entities without having the second level cache activated, hence the error message:
o.h.c.NoCachingEnabledException: Second-level cache is not enabled for usage ...
You need something like this in the hibernate.cfg.xml to use the second level cache (I'm using EHCache as cache provider here):
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
Whether you really need the second level cache is another story.

"Local transaction already has 1 non-XA Resource: cannot add more resources" error

After reading previous questions about this error, it seems like all of them conclude that you need to enable XA on all of the data sources. But:
What if I don't want a distributed
transaction? What would I do if I want to
start transactions on two different
databases at the same time, but
commit the transaction on one database
and roll back the transaction on
the other?
I'm wondering how my code
actually initiated a distributed
transaction. It looks to me like I'm
starting completely separate
transactions on each of the
databases.
Info about the application:
The application is an EJB running on a Sun Java Application Server 9.1
I use something like the following spring context to set up the hibernate session factories:
<bean id="dbADatasource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/dbA"/>
</bean>
<bean id="dbASessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dbADatasource" />
<property name="hibernateProperties">
hibernate.dialect=org.hibernate.dialect.Oracle9Dialect
hibernate.default_schema=schemaA
</property>
<property name="mappingResources">
[mapping resources...]
</property>
</bean>
<bean id="dbBDatasource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/dbB"/>
</bean>
<bean id="dbBSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dbBDatasource" />
<property name="hibernateProperties">
hibernate.dialect=org.hibernate.dialect.Oracle9Dialect
hibernate.default_schema=schemaB
</property>
<property name="mappingResources">
[mapping resources...]
</property>
</bean>
Both of the JNDI resources are javax.sql.ConnectionPoolDatasoure's. They actually both point to the same connection pool, but we have two different JNDI resources because there's the possibility that the two, completely separate, groups of tables will move to different databases in the future.
Then in code, I do:
sessionA = dbASessionFactory.openSession();
sessionB = dbBSessionFactory.openSession();
sessionA.beginTransaction();
sessionB.beginTransaction();
The sessionB.beginTransaction() line produces the error in the title of this post - sometimes. I ran the app on two different sun application servers. On one runs it fine, the other throws the error. I don't see any difference in how the two servers are configured although they do connect to different, but equivalent databases.
So the question is
Why doesn't the above code start
completely independent transactions?
How can I force it to start
independent transactions rather than
a distributed transaction?
What configuration could cause the difference in
behavior between the two application
servers?
Thanks.
P.S. the stack trace is:
Local transaction already has 1 non-XA Resource: cannot add more resources.
at com.sun.enterprise.distributedtx.J2EETransactionManagerOpt.enlistResource(J2EETransactionManagerOpt.java:124)
at com.sun.enterprise.resource.ResourceManagerImpl.registerResource(ResourceManagerImpl.java:144)
at com.sun.enterprise.resource.ResourceManagerImpl.enlistResource(ResourceManagerImpl.java:102)
at com.sun.enterprise.resource.PoolManagerImpl.getResource(PoolManagerImpl.java:216)
at com.sun.enterprise.connectors.ConnectionManagerImpl.internalGetConnection(ConnectionManagerImpl.java:327)
at com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:189)
at com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:165)
at com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:158)
at com.sun.gjc.spi.base.DataSource.getConnection(DataSource.java:108)
at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection(LocalDataSourceConnectionProvider.java:82)
at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446)
at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167)
at org.hibernate.jdbc.JDBCContext.connection(JDBCContext.java:142)
at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:85)
at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1354)
at [application code ...]
1 Why doesn't the above code start completely independent transactions?
The app. server manages the transaction for you which can, if necessary, be a distributed transaction. It enlists all the participants automatically. When there's only one participant, you don't notice any difference with a plain JDBC transaction, but if there are more than one, a distributed transaction is really needed, hence the error.
2 How can I force it to start independent transactions rather than a
distributed transaction?
You can configure the datasource to be XA or Local. The transactional behavior of Spring/Hibernate can also be configured to use either regular JDBC transactions or delegate the management of transactions to the JTA distributed transaction manager.
I suggest you switch the datasource to non-XA and try to configure Spring/Hibernate to use the JDBC transactions. You should find the relevant information in the documentation, here what I suspect is the line to change:
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager" />
This should essentially means that you are not using the app. server distributed transaction manager.
3 What configuration could cause the difference in behavior between the
two application servers?
If you have really exactly the same app and configuration, this means that in one case only one participant is enlisted in the dist. transaction, while there are two in the 2nd case. One participant corresponds to one physical connection to a database usually. Could it be that in one case, you use two schema on two different databases, while in the 2nd case you use two schema on the same physical database? A more probable explanation would be that the datasource were configured differently on the two app. server.
PS: If you use JTA distributed transactions, you should use UserTransaction.{begin,commit,rollback} rather than their equivalent on the Session.
After reading previous questions about this error, it seems like all of them conclude that you need to enable XA on all of the data sources.
No, not all, all except one (as the exception is saying) if your application server supports Logging Last Resource (LLR) optimization (which allows to enlist one non-XA resource in a global transaction).
Why doesn't the above code start completely independent transactions?
Because you aren't. When using beginTransaction() behind EJB Session Beans, Hibernate will join the JTA transaction (refer to the documentation for full details). So the first call just works but the second call means enlisting another transactional resource in the current transaction. And since none of your resources are XA, you get an exception.
How can I force it to start independent transactions rather than a distributed transaction?
See #ewernli answer.
What configuration could cause the difference in behavior between the two application servers?
No idea. Maybe one of them is using at least one XA datasource.

Categories