on the java side, everything works fine but when I look to the V$SESSION special oracle table , and in my log table that records any login or logoff operations, that's a disaster... every single query does a login/logoff operation. So here's my question : Is there any way to configure Spring to have a unique connection to the database or is there something wrong in the way I do the connection ?
Here, my datasource bean configuration :
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>oracle.jdbc.OracleDriver</value>
</property>
<property name="url">
<value>jdbc:oracle:thin:#nanssunorad:1523:nanorad3</value>
</property>
<property name="username">
<value>foo</value>
</property>
<property name="password">
<value>bar</value>
</property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation">
<value>hibernateESign.cfg.xml</value>
</property>
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
<bean id="IXalVaParametresDAO" class="fr.asterion.archivage.hibernate.XalVaParametresDAO">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
In my app, to get the DAO for the database parameters, I do a
IXalVaParametresDAO parametreDAO = (IXalVaParametresDAO) ConfigApplication
.getApplicationContext(this.log).getBean("IXalVaParametresDAO");
And at last, in my DAO class, I do someting like this :
public class XalVaParametresDAO implements IXalVaParametresDAO
{
private HibernateTemplate hibernateTemplate;
public void setSessionFactory(SessionFactory sessionFactory)
{
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
public List<XalVaParametres> findAll()
{
log.debug("finding all XalVaParametres instances");
try
{
String queryString = "from XalVaParametres";
List lst = this.hibernateTemplate.find(queryString);
In my app, each time I call the "find" method, it does a DB login/logoff. I guess the problem is the same on another DB. Am I doing the things right ? I guess not. I wish the HibernateTemplate would create and keep the session open once and for all. Is that possible ?
Thanks for your ideas
Manux
Use a pooling DataSource, e.g. Apache Commons / DBCP's BasicDataSource
Reference:
Spring JDBC > Controlling Database Connections
Spring ORM > Hibernate > SessionFactory setup in a Spring
container
It's not recommended to use DriverManagerDataSource in production, since it doesn't perform connection pooling.
You need to use connection pool instead, such as c3p0 or Apache DBCP.
Its better to use the connection pooling of the application server and specify the jndi in spring xml file :
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/DSTest"/>
</bean>
You can use the native oracle datasource with connection caching like:
<bean id="myDataSource" class="oracle.jdbc.pool.OracleDataSource" destroy-method="close">
<property name="connectionCachingEnabled" value="true"/>
<property name="URL">
<value>${jdbc.url}</value>
</property>
<property name="user">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
<property name="connectionCacheProperties">
<value>
MinLimit:1
MaxLimit:1
InitialLimit:1
ConnectionWaitTimeout:120
InactivityTimeout:180
ValidateConnection:true
MaxStatementsLimit:0
</value>
</property>
</bean>
Related
Working with common spring application I can define dataSource or Hibernate session factory as bean and then simply autowire them. like that:
#Autowired
private DataSource dataSource;
or
#Autowired
private SessionFactory sessionFactory;
For now I want to create some tables and store them in alfresco. How get dataSource or sessionFactory (if alfresco uses hibernate) which is pointed to alfresco database?
Inject the dataSource bean defined in core-services-context.xml:
<bean id="dataSource" class="org.alfresco.config.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jdbc/dataSource</value>
</property>
<property name="defaultObject">
<ref bean="defaultDataSource" />
</property>
</bean>
using your-config-context.xml, for example ibatis-context.xml:
<bean id="repoSqlSessionFactory" class="org.alfresco.ibatis.HierarchicalSqlSessionFactoryBean">
<property name="resourceLoader" ref="dialectResourceLoader"/>
<property name="dataSource" ref="dataSource"/>
<property name="configLocation">
<value>classpath:alfresco/ibatis/alfresco-SqlMapConfig.xml</value>
</property>
</bean>
Be aware that:
Alfresco incorporates Hibernate and iBATIS open source database
abstraction layers to allow it to be ported to a number of different
database management systems.
so, it is preferred to use MyBatis-Spring and org.mybatis.spring.SqlSessionTemplate, for example org.alfresco.repo.domain.audit.ibatis.AuditDAOImpl.java:
<bean id="auditSqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="repoSqlSessionFactory"/>
</bean>
<bean id="auditDAO" class="org.alfresco.repo.domain.audit.ibatis.AuditDAOImpl">
<property name="sqlSessionTemplate" ref="auditSqlSessionTemplate"/>
<property name="contentService" ref="contentService"/>
<property name="contentDataDAO" ref="contentDataDAO"/>
<property name="propertyValueDAO" ref="propertyValueDAO"/>
</bean>
This Alfresco 5 and Spring tutorial might be helpful for you.
I am using Spring and trying to setup a global transaction spanning over two MS SQL Server DBs. The app is running inside Tomcat 6.
I have these definitions:
<bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
....
</bean>
<bean id="sessionFactory1"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource1"/>
....
</bean>
<bean id="hibernateTransactionManager1"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory1"/>
</property>
</bean>
<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
....
</bean>
<bean id="sessionFactory2"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource2"/>
....
</bean>
<bean id="hibernateTransactionManager2"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory2"/>
</property>
</bean>
Then also, each DAO is linked either to sessionFactory1 or to sessionFactory2.
<bean name="stateHibernateDao" class="com.project.dao.StateHibernateDao">
<property name="sessionFactory" ref="sessionFactory1"/>
</bean>
Also, I recently added these two.
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
<property name="forceShutdown" value="false" />
<property name="transactionTimeout" value="300" />
</bean>
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300" />
</bean>
I am trying to programmatically manage the global transaction
(this is some old legacy code and I don't want to change it too
much so I prefer keeping this managed programmatically).
So now I have this UserTransaction ut (injected from Spring), so I call ut.begin(), do some DB/DAO operations to the two DBs through the DAOs, then I call ut.commit().
The thing is that even before the ut.commit() call, I can see the data is already committed to the DBs?!
I don't think Atomikos is aware of my two DBs, their data sources, session factories, etc. I don't think it starts any transactions on them. Looks like they are not enlisted at all in the global transaction.
To me it seems that each DB/DAO operation goes to the SQL Server on its own, so SQL Server creates an implicit transaction for just that DAO/DB operation, applies the operation and commits the implicit the transaction.
But 1) and 2) are just guesses of mine.
My questions:
Do I need to start the two DB transactions myself (but OK, this is what I am currently doing and I am trying to get rid of; that's why I am trying to use Atomikos to start with)?
How I can configure all this correctly so that when I call ut.begin() it begins a global transaction to the two DBs and when I call ut.commit() it commits it?
I haven't played with JTA recently so seems to me I am missing something quite basic here. What is it?
Edit 1
<bean id="globalTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransaction" ref="atomikosUserTransaction"/>
<property name="transactionManager" ref="atomikosTransactionManager" />
<property name="allowCustomIsolationLevels" value="true" />
<property name="transactionSynchronization" value="2" />
</bean>
I´ve my hibernate configuration inside my spring-context, but after a little time of use I´m getting the too many connections error. Here is my code:
Spring context:
<!-- Beans Declaration -->
<bean id="Usuarios" class="com.proximate.model.Usuarios"/>
<!-- Service Declaration -->
<bean id="UsuariosService" class="com.proximate.service.UsuariosService">
<property name="usuariosDAO" ref="UsuariosDAO" />
</bean>
<!-- DAO Declaration -->
<bean id="UsuariosDAO" class="com.proximate.dao.UsuariosDAO">
<property name="sessionFactory" ref="SessionFactory" />
</bean>
<bean id="DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mydb" />
<property name="user" value="user" />
<property name="password" value="password" />
<property name="maxPoolSize" value="50" />
<property name="maxStatements" value="0" />
<property name="minPoolSize" value="5" />
</bean>
<!-- Session Factory Declaration -->
<bean id="SessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="DataSource" />
<property name="annotatedClasses">
<list>
<value>com.proximate.model.Usuarios</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
</bean>
<!-- Enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="txManager"/>
<context:annotation-config />
<!-- Transaction Manager is defined -->
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="SessionFactory"/>
</bean>
and here is how I use my session factory inside my dao:
private SessionFactory sessionFactory;
private HibernateTemplate hibernateTemplate;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
Query query = hibernateTemplate.getSessionFactory().getCurrentSession().createSQLQuery("SELECT ID FROM usuarios");
Integer cantidad = new Integer(((BigInteger) query.uniqueResult()).intValue());
Why is my code opening so many connections. I heard that using a HibernateUtil class to load a session after logging might be what I need, but how do you implement it when using spring??
Thanks in advance!!
I don't know much about hibernate itself, but i think closing the session might help.
That's how JPAs EntityManager works - you have to close it to close underlaying connection.
It looks like your hibernate query is global? I would guess the cause is probably because it is not contained in a method with a transactional annotation around it.
I'm using spring + hibernate + jersey in my application. I want to use transactions so I used spring's #Transactional annotation in my service layer. This is my hibernate.cfg.xml:
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/db</property>
<property name="hibernate.connection.username">user</property>
</session-factory>
</hibernate-configuration>
I haven't used session_context here so spring can manage it. In my applicationCOntext.xml, I have defined transactionManager:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/db"/>
<property name="user" value="username"/>
</bean>
<context:annotation-config/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="packagesToScan">
<list>
<value>com.hibernate.pojos</value>
</list>
</property>
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
All urls matching /api/v1/* map to a servlet named jersey and servlet class used is com.sun.jersey.spi.spring.container.servlet.SpringServlet to which I have passed com.services as package to scan. In this package I have a class:
#Path("/app")
#Component
public class testApi() {
#Autowired
private DAOImpl daoimpl;
#POST
#Path("/create")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#Transactional(rollbackFor = {Exception.class})
public Map<String,Object> testHello(user u) {
Map response = daoimpl.save(u);
return response;
}
}
The class daoimpl has the sessionFactory autowired and uses sessionFactory.getCurrentSession() method to get session. The method daoimpl.save(obj) just saves it in db. Since I have marked testHello as transactional, I expect a transaction to begin which is managed by spring and then control should go to daoimpl where the actual save happens. But I get save is not valid without active transaction. I have seen lot of posts where session_context is mentioned in hibernate config and because of that, spring is unable to handle transactions. But in my case, I have ensured that I dont provide any session_context. What am I missing? I even tried adding #transactional to DAO since in my sample app, Im just issuing one DB call for a service. But this didnt work either.
Well could be that you are specifying a session factory via hibernate.cfg.xml and then again in Spring which gets passed to the transaction manager.
Not sure to be honest however I have never used a hibenate.cfg.xml and then following works for me (with the transactional config added as you have specified). This also gives you the advantage of specifying your connection params as properties and allowing you to easily swap db configs via Spring Profiles or some other mechanism.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<list>
<value>uk.co.xyz.domain</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">${hibernate.showsql}</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.ddlauto}</prop>
<prop key="hibernate.cache.use_second_level_cache">${hibernate.enablecache}</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
</beans>
See also here which actually suggests is shouldn't matter:
applicationContext.xml with datasource or hibernate.cfg.xml. Difference?
I am using Hibernate 4, Spring 3, JSF 2.0 and Weblogic 10.3.6 as server.
I have created datasource on Weblogic server and in applicationContext.xml I have defined datasource as
<!-- Data Source Declaration -->
<bean id="DataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/myDS"/>
</bean>
If I would want to use the P6Spy for logging SQL parameters, how can and where I should add the following in applicationcontext.xml?
<property name="hibernate.connection.driver_class">com.p6spy.engine.spy.
P6SpyDriver</property>
Any help is highly appreciable.
Thanks
The easiest way to integrate p6spy using spring is to use the P6DataSource class. The P6DataSource class is just a proxy for the real data source. This lets you obtain the real data source using any of the spring data source factory implementations.
<bean id="dataSource" class="com.p6spy.engine.spy.P6DataSource">
<constructor-arg>
<bean id="DataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/myDS"/>
</bean>
</constructor-arg>
</bean>
If you are using an XADatasource, just change the classname to P6ConnectionPoolDataSource as shown below. Note: P6ConnectionPoolDataSource implements the ConnectionPoolDataSource and XADataSource interfaces.
<bean id="dataSource" class="com.p6spy.engine.spy.P6ConnectionPoolDataSource">
<constructor-arg>
<bean id="DataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/myDS"/>
</bean>
</constructor-arg>
</bean>
You need to create bean of session factory in applicationContext.xml file as follows:
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.p6spy.engine.spy.
P6SpyDriver" />
<property name="url" value="jdbc\:mysql\://localhost\:3306/testdb" />
<property name="username" value="my_username" />
<property name="password" value="my_password" />
</bean>
Please refer to: http://www.mkyong.com/hibernate/how-to-display-hibernate-sql-parameter-values-solution/ for more about P6Spy library.
We can omit "dataSource" bean and directly write properties. Ref: how to configure hibernate config file for sql server