Setting global query timeout in hibernate - java

How can i configure a default query timeout in application level. I am using spring , hibernate and db2 as a backend. Setting the timeout in datasource level is not an option as we are using an old version of IBM websphere. I tried configuring defaultTimeout in transaction manager but that is not helping. I don't want to integrate c3p0 connection pooling also. Is there any other options that hibernate provide for setting a global query timeout in application level , if yes how that is configured .
Thanks in advance

Here is the spring config configuration.
<bean class="org.springframework.jdbc.core.JdbcTemplate">
<property name="queryTimeout" value="60"/>
</bean>

Related

Hibernate and Spring Connection Pool Defaults

I am working on an application which is based on Hibernate 5.1.9.Final and Spring 4.3.6.RELEASE
What I am trying to discover is what the default values for connecting to the relational database are, such as connection_timeout, maxConnections, etc.
I am trying to understand this existing project, and I don't have any of this configuration on that, but still, I see several connections on the Database -> Postgres.
How to discover what the defaults are? Are there defaults values? And what is the default connection pool framework? C3p0?
The default connection pooling mechanisms in hibernate are not production, not even performance testing ready. Here is a quotation from hibernate documentation
Hibernate's own connection pooling algorithm is, however, quite
rudimentary. It is intended to help you get started and is not
intended for use in a production system, or even for performance
testing. You should use a third party pool for best performance and
stability. Just replace the hibernate.connection.pool_size property
with connection pool specific settings. This will turn off Hibernate's
internal pool. For example, you might like to use c3p0.
The property setting up the number of pooled connections is:
hibernate.connection.pool_size
Here is an example C3P0 configuration:
hibernate.connection.driver_class = org.postgresql.Driver
hibernate.connection.url = jdbc:postgresql://localhost/mydatabase
hibernate.connection.username = myuser
hibernate.connection.password = secret
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=20
hibernate.c3p0.timeout=1800
hibernate.c3p0.max_statements=50
hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
recently Hikari is very popular choice for connection pooling.
https://brettwooldridge.github.io/HikariCP/
Here is an example set of Hikari properties:
<property name="hikari.dataSource.cachePrepStmts">true</property>
<property name="hikari.dataSource.prepStmtCacheSize">250</property>
<property name="hikari.dataSource.prepStmtCacheSqlLimit">2048</property>
<property name="hikari.dataSource.useServerPrepStmts">true</property>
<property name="hikari.maximumPoolSize">30</property>
<property name="hikari.idleTimeout">30000</property>
<!-- Database connection properties -->
<property name="hibernate.hikari.dataSourceClassName">com.mysql.jdbc.jdbc2.optional.MysqlDataSource</property>
<property name="hikari.dataSource.url">jdbc:mysql://127.0.0.1/sample</property>
<property name="hikari.dataSource.user">root</property>
<property name="hikari.dataSource.password">tiger</property>
source:
https://self-learning-java-tutorial.blogspot.com/2016/01/hibernate-hikaricp-example.html

Spring Jedis connection not returned to pool

My app is made of a Spring rest controller calling a service using redis.
I am using spring boot starter redis 1.2.5 and I have defined a template in my beans.xml file:
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${spring.redis.host}"
p:use-pool="true"
p:port="${spring.redis.port}"
/>
<bean id="redisTemplateForTransaction" class="org.springframework.data.redis.core.RedisTemplate"
p:connection-factory-ref="jedisConnectionFactory"
p:keySerializer-ref="stringRedisSerializer"
p:valueSerializer-ref="jsonRedisSerializerForTransaction"
p:enableTransactionSupport="true">
<qualifier value="redisTemplateForTransaction" />
</bean>
When I launch more than 8 queries my app blocks. I understand I have reached the default number of connections in the pool.
Why aren't the connections returned automatically at the end of the request processing ?
How to work in a transactional mode so that any incoming request will get its redis connection and return it at the end of the processing ?
You need to enable transaction management for your application by providing a PlatformTransactionManager bean.
The easiest way to do so is adding #EnableTransactionManagement to your Spring Boot application. If that's not possible, configure a PlatformTransactionManager bean. Reusing an existing DataSourceTransactionManager is the easiest way. If you do not use a JDBC-compliant database, simply drop in a H2 in-memory database.
If you want to use a JTA transaction manager, see this blog post: https://spring.io/blog/2011/08/15/configuring-spring-and-jta-without-full-java-ee/
HTH, Mark

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/

Connection pooling with hibernate 4 and struts2

I have implemeted a web application using Struts2 and Hibernate 4.3.5
I am facing some problems and need some clarification on some connection pooling properties.
To make connection pooling with hibernate I have used c3p0-0.9.1.jar
Below are the connection pooling Properties of c3p0 in hibernate.cfg.xml
<!-- Connection Pooling using c3p0 -->
<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">10</property>
<property name="hibernate.c3p0.timeout">500</property>
<property name="hibernate.c3p0.max_statements">2</property>// I heard somewhere that this property improves performance.. But dont know How it improves
<property name="hibernate.c3p0.idle_test_period">300</property>
<property name="hibernate.c3p0.preferredTestQuery">
select sysdate from dual;
</property>
In my application I have used * session-per-request* patterns by setting following property in hibernte-cfg.xml
<!-- To open the connection when the request hits. -->
<property name="hibernate.current_session_context_class">thread</property>
When I use this I am getting Session as following
//Here MyHiberantaeUtil is my own class having singleton pattern and Static block
// To read hibernate-cfg.xml and will create SessionFactroy object.
SessionFactory sessionFactory = MyHibernateUtil.getSessionFactory();
Session session = sessionFactory.getCurrentSession();
As per the documentation .. When I use this pattern connection should be created when request is requested and should be closed when request completed.
For my case Its creating connection .. i.e I can get Session Using this getCurrentSession() But its not closing when The request ended.
To test connection pooling I have used jconsole tool in my jdk
Where I can see
`numBusyConection = 2(If that is two requests.)`
I would like to know is there any thing I missed . Why thread property is not working as expected ?
And how to say that Request has completed and request has generated ?
Is session-per-request is best pattern or better to go any other patterns ?
I did not find this class `org.hibernate.connection.C3P0ConnectionProvider` in any jar files.. But My application is connecting to DB and working fine.
Please help thanks in advance.
The JDBC connection is opened when first needed and closed when the Session is closed. You need to manually close the session when you go out of your Service layer:
session.close();
Otherwise the connections won't be closed and you'll starve the connection pool.
It's a better idea to use Spring, because it has support for automatically creating/closing sessions for you. Your MyHibernateUtil is no match for what Spring has to offer:
local transactions
global transactions
transaction annotations and automatic commit on success or rollback on runtime exceptions
Setting up Spring with Hibernate is as easy as using the HibernateUtil class.

Spring transaction management to work with multiple data sources

This might be a repetitive question for you, but I couldn't find (atleast I couldn't understand) a satisfactory answer, hence asking again.
I am working with two data sources (MySQL and Oracle). Following is a flow of execution:
Main method-A calls method-B (Which writes into Oracle DB) then it(Method-A) calls method-C (Which writes into mySQL DB) then it(Method-A) calls method-D(Which writes into Oracle DB).
If failure occurs at any of place, everything should be rolled back. Currently only changes in Oracle DB are getting rolled back & mySQL DB is not getting rolled back.
I have defined two transactional managers.
=========> First <=========
<tx:annotation-driven transaction-manager="txManager" mode='proxy' proxy-target-class='true’/>
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="SessionFactory" />
</bean>
<bean id=“SessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean” parent="AbstractSessionFactory" depends-on="AppConfigHelper”>
<property name="hibernateProperties”>
...
ORACLE DB Properties
</property>
</bean>
<aop:aspectj-autoproxy/>
==============================
=========> Second <=========
<tx:annotation-driven transaction-manager="txManager2" mode='proxy' proxy-target-class='true'/>
<bean id="txManager2" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="SessionFactory2" />
<qualifier value="CherryTransaction" />
</bean>
<aop:aspectj-autoproxy/>
<bean id="SessionFactory2" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" parent="AbstractSessionFactory2" depends-on="AppConfigHelper">
<property name="hibernateProperties">
...
MYSQL DB Properties
</property>
</bean>
==============================
On top of method-A I have used #Transactional annotation
On top of method-B I have used #Transactional annotation
On top of method-C I have used #Transactional("txManager2")
annotation
On top of method-D I have used #Transactional annotation
Question Is:
Why is MySQL changes are not getting rolled back?
Is the only way to get this working is to use Global transaction management using JTA? (Its a legacy system, and this is the only place where I need to interact with two DBs)
Can you please point me to an example / tutorial where this kind case is handled?
Sincerely thanks for reading this!
For that to work, AFAIK you'd need to use JTA. Even that won't help if you're using a storage engine in MySQL that doesn't support transactions. With MySQL, only InnoDB and BDB storage engines support transactions.
If you are using MySQL with storage engine that supports transactions, you need to configure XA drivers for both Oracle and MySQL datasource and ensure that both datasources are enlisted in the transaction of your container. Spring then needs to participate in the same transaction. You can't use HibernateTransactionManager for this, but need the JtaTransactionManager, as explained in this thread.
So, what you need for this to work is
Use InnoDB or BDB storage engines on MySQL
Configure XA datasources in your application server instead of regular ones
Use JtaTransactionManager on Spring configuration

Categories