Where to place c3p0 properties in configuration file? - java

I am using spring/hibernate integrated application. i have configured c3p0 connection pooling. the problem is if i set c3p0 properties in hibernate properties section then those properties are not considered and default configuration is taken. if i set the same properties for combopooled datasource then they are considered. where is the best place to place c3p0 properties.
Below configuration works:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${db.driverClassName}" />
<property name="jdbcUrl" value="${db.url}" />
<property name="user" value="${db.username}" />
<property name="password" value="${db.password}" />
<!-- c3p0 properties -->
<property name="minPoolSize" value="5" />
<property name="maxPoolSize" value="20" />
<property name="maxStatements" value="0" />
<property name="preferredTestQuery" value="select * from sometable" />
</bean>
<bean name="wygSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mappingLocations" value="classpath:hibernate/module/*.hbm.xml" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
<prop key="hibernate.connection.pool.size">20</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
</bean>
This does not work:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${db.driverClassName}" />
<property name="jdbcUrl" value="${db.url}" />
<property name="user" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>
<bean name="wygSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mappingLocations" value="classpath:hibernate/module/*.hbm.xml" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
<prop key="hibernate.connection.pool.size">20</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<!-- c3p0 properties -->
<prop key="hibernate.c3p0.min_size">5</prop>
<prop key="hibernate.c3p0.max_size">20</prop>
<prop key="hibernate.c3p0.timeout">300</prop>
<prop key="hibernate.c3p0.max_statements">0</prop>
<prop key="hibernate.c3p0.preferredTestQuery">select * from sometable</prop>
</props>
</property>
</bean>

I was getting the same problem and it took time to figure out the solution.
I use Hibernate 4.0.1 and mysql 5.1(no spring framework) and I was facing the issue. First make sure that you configured the c3p0 jars properly which are essential.
I used these properties in hibernate.cfg.xml
<property name="hibernate.c3p0.validate">true</property>
<property name="hibernate.connection.provider_class">org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.preferredTestQuery">SELECT 1;</property>
<property name="hibernate.c3p0.testConnectionOnCheckout">true</property>
<property name="hibernate.c3p0.idle_test_period">10</property>
<property name="hibernate.c3p0.acquireRetryAttempts">5</property>
<property name="hibernate.c3p0.acquireRetryDelay">200</property>
<property name="hibernate.c3p0.timeout">40</property>
But it's of no use 'cause C3p0 was still taking the default properties not the properties which I set in hibernate.cfg.xml, You can check it in logs. So, I searched many websites for right solution and finally I came up with this. remove the C3p0 properties in cfg.xml and create c3p0-config.xml in the root path(along with cfg.xml) and set properties as follows.
<c3p0-config>
<default-config>
<property name="automaticTestTable">con_test</property>
<property name="checkoutTimeout">40</property>
<property name="idleConnectionTestPeriod">10</property>
<property name="initialPoolSize">10</property>
<property name="maxPoolSize">20</property>
<property name="minPoolSize">5</property>
<property name="maxStatements">50</property>
<property name="preferredTestQuery">SELECT 1;</property>
<property name="acquireRetryAttempts">5</property>
<property name="acquireRetryDelay">200</property>
<property name="maxIdleTime">30</property>
</default-config>
</c3p0-config>
but if you run, ORM takes the jdbc connection but not C3p0 connection pool 'cause we should add these properties in hibernate.cfg.xml
<property name="hibernate.c3p0.validate">true</property>
<property name="hibernate.connection.provider_class">org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider</property>
now everything works fine(At least it worked fine for me) and the issue is solved.
check the following for references.
http://www.mchange.com/projects/c3p0/index.html#configuring_connection_testing
https://community.jboss.org/wiki/HowToConfigureTheC3P0ConnectionPool
I hope this solves your problem.

Related

Getting "Unknown system variable 'tx_isolation'" error using c3p0 connection pooling

I am trying to use c3pO connection pooling but getting below error:
Unknown system variable 'tx_isolation'
I am using below jars:
mysql-connector-java-8.0.11.jar
c3p0-0.9.5.3.jar
mchange-commons-java-0.2.15.jar
And below configuration:
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="com.mysql.cj.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/customer_tracker?useSSL=false&serverTimezone=UTC" />
<property name="user" value="root" />
<property name="password" value="root" />
<!-- these are connection pool properties for C3P0 -->
<property name="minPoolSize" value="3" />
<property name="maxPoolSize" value="10" />
<property name="maxIdleTime" value="30000" />
</bean>
<!-- Step 2: Setup Hibernate session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="packagesToScan" value="com.springdemo.entity" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>

java.sql.SQLTransientConnectionException: spring HikariCP - Connection is not available, request timed out afte

I've catched java.sql.SQLTransientConnectionException: springHikariCP - Connection is not available, request timed out after 30001ms.
First code block works well, second (CP) does not work.
What is wrong and how fix this?
JDK - 1.8.0_73.
HikariCP - 2.4.5.
Spring - 4.2.5.RELEASE.
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${connection.driverClassName}"/>
<property name="username" value="${connection.userName}"/>
<property name="password" value="${connection.password}"/>
<property name="url" value="${connection.url}"/>
</bean>
CP
<bean id="hikariConfiguration" class="com.zaxxer.hikari.HikariConfig">
<property name="poolName" value="springHikariCP"/>
<property name="dataSourceClassName" value="${connection.dataSourceClassName}"/>
<property name="maximumPoolSize" value="${connection.pool.maximumPoolSize}"/>
<property name="idleTimeout" value="${connection.pool.idleTimeout}"/>
<property name="dataSourceProperties">
<props>
<prop key="url">${connection.url}</prop>
<prop key="user">${connection.userName}</prop>
<prop key="password">${connection.password}</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy- method="close">
<constructor-arg ref="hikariConfiguration"/>
</bean>
//...............
#CONNECTION
connection.dataSourceClassName=org.hsqldb.jdbc.JDBCDataSource
connection.url=jdbc:hsqldb:mem:dbtest-local
connection.userName=sa
connection.password=
#POOL
connection.pool.maximumPoolSize=1
connection.pool.idleTimeout=28500
#HIBERNATE
hibernate.hbm2ddl.auto=create-drop
hibernate.dialect=H2Dialect
hibernate.show_sql=true
If you use the dataSourceClassName, you should not provide the jdbc url.
Instead, you should add the host, dbname, etc. as properties. See the example on github:
dataSourceClassName=org.postgresql.ds.PGSimpleDataSource
dataSource.user=test
dataSource.password=test
dataSource.databaseName=mydb
dataSource.portNumber=5432
dataSource.serverName=localhost
Otherwise, you should not use the dataSourceClassName. Try with:
<bean id="hikariConfiguration" class="com.zaxxer.hikari.HikariConfig">
<property name="poolName" value="springHikariCP" />
<property name="maximumPoolSize" value="${connection.pool.maximumPoolSize}" />
<property name="idleTimeout" value="${connection.pool.idleTimeout}" />
<property name="jdbcUrl" value="${connection.url}" />
<property name="dataSourceProperties">
<props>
<prop key="user">${connection.userName}</prop>
<prop key="password">${connection.password}</prop>
</props>
</property>
</bean>
This is working for me in local.

Hibernate/Spring DataSource and RDS Replica

I would like to setup a RDS Read Replica to forward some of the read requests to it. I've annotated all my "read" Dao methods with:
#Transactional(readOnly = true)
Now I am struggling with datasource configuration. I expected that it would be really easy, but it seems it isn't. How can I tell the datasource/hibernate that there is a read replica available on certain endpoint?
Currently my configuration looks like:
<bean id="mainDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://${master-url}:3306/${db-name}?useSSL=true&requireSSL=true&verifyServerCertificate=false"/>
<property name="user" value="${user}"/>
<property name="password" value="${password}"/>
<!-- these are C3P0 properties -->
<property name="acquireIncrement" value="3"/>
<property name="minPoolSize" value="3"/>
<property name="maxPoolSize" value="10"/>
<property name="maxIdleTime" value="3600"/>
<!-- 1 hour -->
<property name="maxConnectionAge" value="7200"/>
<property name="maxIdleTimeExcessConnections" value="600"/>
<property name="idleConnectionTestPeriod" value="60"/>
<property name="testConnectionOnCheckin" value="true"/>
<property name="testConnectionOnCheckout" value="false"/>
<property name="preferredTestQuery" value="SELECT 1"/>
</bean>
<bean id="mainSessionFactory" name="mainSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" depends-on="mainDataSource">
<property name="packagesToScan">
<list>
<value>com....</value>
</list>
</property>
<property name="dataSource" ref="mainDataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.connection.tinyInt1isBit">true</prop>
<prop key="hibernate.connection.transformedBitIsBoolean">true</prop>
<prop key="hibernate.hbm2ddl.auto">none</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.connection.CharSet">UTF-8</prop>
<prop key="hibernate.connection.characterEncoding">UTF-8</prop>
<prop key="hibernate.connection.useUnicode">true</prop>
<prop key="hibernate.jdbc.batch_size">40</prop>
</props>
</property>
</bean>
Any help/advice would be highly appreciated!
Best Regards,
Maksim

Spring-Hibernate using multiple datasource/database

I'm working on a web application that uses Spring MVC 3 and Hibernate
I want to use 2 datasource MySql and Oracle databases for my web application,
I've been read many tutorial and problem solving for "spring-hibernate multiple datasource/database"
for example :
directjump2java.blogspot.com
stackoverflow
forum spring
and etc.
but when every single time I run it, the config just read my first database config (MySql)
and show this error Table 'db_prod.ksei_lookup_holiday' doesn't exist db.prod is my first database(MySql) and KSEI_LOOKUP_HOLIDAY is my second database (Oracle),
this is my spring.xml
<tx:annotation-driven transaction-manager="transactionManager"/>
<tx:annotation-driven transaction-manager="transactionManagerSOAAPP"/>
<context:annotation-config />
<context:component-scan base-package="prod.support" />
<!-- Database MySql, Desktop -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/db_prod" />
<property name="username" value="root" />
<property name="password" value="shikamaru" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration"></property>
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="packagesToScan" value="prod.support.model.splatter" />
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory">
</bean>
<!-- Database Oracle, Schema : SOAAPP -->
<bean id="dataSourceSOAAPP" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#localhost:1521:XE" />
<property name="username" value="splatter" />
<property name="password" value="shikamaru" />
</bean>
<bean id="sessionFactorySOAAPP"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration"></property>
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="packagesToScan" value="prod.support.model.soaapp" />
</bean>
<bean id="transactionManagerSOAAPP"
class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactorySOAAPP">
</bean>
this is my DAO Implementation for my first database (MySql)
#Repository
#Qualifier(value="sessionFactory")
public class UserDaoImpl extends HibernateDaoSupport implements UserDao{
#Autowired
private UserDaoImpl(SessionFactory sessionFactory){
setSessionFactory(sessionFactory);
}
this is my DAO Implementation for my second database (Oracle)
#Repository
#Qualifier(value="sessionFactorySOAAPP")
public class UpdateKSEIDaoImpl extends HibernateDaoSupport implements UpdateKSEIDao{
#Autowired
private UpdateKSEIDaoImpl(SessionFactory sessionFactorySOAAPP){
setSessionFactory(sessionFactorySOAAPP);
}
any help will be pleasure :)
The problem is that you have used
<property name="dataSource" ref="dataSource"></property> in sessionFactorySOAAPP.
You should have used <property name="dataSource" ref="dataSourceSOAAPP"></property>
If you check "sessionFactorySOAAPP" then the below property name should be 'dataSourceSOAAPP' not the 'dataSource'.
this my configuration file:
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/gl?characterEncoding=UTF-8" />
<property name="username" value="root" />
<property name="password" value="2238295" />
</bean>
<bean id="mainDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/gl_main?characterEncoding=UTF-8" />
<property name="username" value="root" />
<property name="password" value="2238295" />
</bean>
<!-- Hibernate 4 SessionFactory Bean definition -->
<bean id="sfAccounting"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.gl.domain.accounting" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.connection.useUnicode">true</prop>
<prop key="hibernate.connection.characterEncoding">UTF-8</prop>
<prop key="hibernate.connection.charSet">UTF-8</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
</bean>
<!-- Hibernate 4 SessionFactory Bean definition -->
<bean id="sfCommon"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="mainDataSource" />
<property name="packagesToScan" value="com.gl.domain.common" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.connection.useUnicode">true</prop>
<prop key="hibernate.connection.characterEncoding">UTF-8</prop>
<prop key="hibernate.connection.charSet">UTF-8</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
</bean>
<tx:annotation-driven transaction-manager="txnManagerAccounting"/>
<tx:annotation-driven transaction-manager="txnManagerCommon"/>
<bean id="txnManagerAccounting"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sfAccounting" />
</bean>
<bean id="txnManagerCommon"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sfCommon" />
</bean>
<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
#geoand is correct in the error he spotted. Other than that the context xml seems correct and works for me.
However, for me, this only works if #qualifier is with the #Autowired.
#Repository
public class BusinessDaoImpl implements BusinessDao
{
#Autowired
#Qualifier(value="sessionFactory")
SessionFactory sessionFactory;

configure jta transaction manager using spring?

I have below configuration in my spring config file. I am using Spring3, Hibernate4 and Tomcat7.
<jee:jndi-lookup id="wcDataSource" jndi-name="java:comp/UserTransaction" resource-ref="false" environment-ref="remoteEnv" />
<util:properties id="remoteEnv">
<prop key="java.naming.provider.url">jnp://jndi.myURL.me:1099</prop>
<prop key="java.naming.factory.url.pkgs">org.jboss.naming:org.jnp.interfaces</prop>
<prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
<prop key="jnp.disableDiscovery">true</prop>
</util:properties>
<bean id="dataSourceKS" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${driverClassName}" />
<property name="jdbcUrl" value="${url}" />
<property name="user" value="${username}" />
<property name="password" value="${password}" />
<!-- pool sizing -->
<property name="initialPoolSize" value="15" />
<property name="minPoolSize" value="10" />
<property name="maxPoolSize" value="20" />
<property name="acquireIncrement" value="3" />
<property name="maxStatements" value="6000" />
<property name="maxStatementsPerConnection" value="300" />
</bean>
<bean name="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSourceKS"/>
<property name="annotatedClasses">
<list>
<value>com.sample.MyBean</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.use_sql_comments">true</prop>
<prop key="hibernate.jdbc.batch_size">50</prop>
</props>
</property>
</bean>
Now how can i configure JTATransactionManager here to use #Transactional? Here i have wcDataSource and dataSourceKS. Thanks!
Thanks!
The JtaTransactionManager does not need to know about the DataSource, or any other specific resources, because it uses the container’s global transaction management infrastructure.
So conf file should look like this
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
See http://lafernando.com/2011/01/05/xa-transactions-with-apache-dbcp/ which does it in code but which you should be able to translate to a spring configuration.
Which would result in something like this.
<jee:jndi-lookup id="userTransaction" jndi-name="java:comp/UserTransaction" resource-ref="false" environment-ref="remoteEnv" />
<jee:jndi-lookup id="jtaTransactionManager" jndi-name="java:comp/TransactionManager" resource-ref="false" environment-ref="remoteEnv" />
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<constructor-arg ref="userTransaction"/>
<constructor-arg ref="jtaTransactionManager"/>
</bean>
<util:properties id="remoteEnv">
<prop key="java.naming.provider.url">jnp://jndi.myURL.me:1099</prop>
<prop key="java.naming.factory.url.pkgs">org.jboss.naming:org.jnp.interfaces</prop>
<prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
<prop key="jnp.disableDiscovery">true</prop>
</util:properties>
<bean id="oracleXaDataSource" class="oracle.jdbc.xa.client.OracleXADataSource">
<property name="user" value="${username}" />
<property name="password" value="${password}" />
<property name="url" value="${url}" />
</bean>
<bean id="dataSourceKS" class="org.apache.commons.dbcp.managed.BasicManagedDatasource">
<property name="transactionManager" ref="jtaTransactionManager" />
<property name="xaDataSourceInstance" ref="oracleXaDataSource" />
<property name="initialPoolSize" value="15" />
<property name="minPoolSize" value="10" />
<property name="maxPoolSize" value="20" />
<property name="acquireIncrement" value="3" />
<property name="maxStatements" value="6000" />
<property name="maxStatementsPerConnection" value="300" />
</bean>
<bean name="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="jtaDataSource" ref="dataSourceKS"/>
// .. other hibernate properties
</bean>
Note the change to commons-dbcp as c3p0 doesn't have XA capable implementations.

Categories