Exception when using custom session factory implementation - java

I am using Spring with Hibernate for transaction management. For SessionFactory, I have a custom implementation class HRSessionFactory as below:
package com.practice.swh.entity;
import java.io.Serializable;
import java.sql.Connection;
import java.util.Map;
import java.util.Set;
import javax.naming.NamingException;
import javax.naming.Reference;
import org.hibernate.Cache;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionBuilder;
import org.hibernate.SessionFactory;
import org.hibernate.StatelessSession;
import org.hibernate.StatelessSessionBuilder;
import org.hibernate.TypeHelper;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.metadata.CollectionMetadata;
import org.hibernate.stat.Statistics;
public class HRSessionFactory implements SessionFactory {
private SessionFactory sessionFactory;
#Override
public void close() throws HibernateException {
sessionFactory.close();
}
#Override
public void evict(Class arg0, Serializable arg1) throws HibernateException {
sessionFactory.evict(arg0, arg1);
}
#Override
public void evict(Class arg0) throws HibernateException {
sessionFactory.evict(arg0);
}
#Override
public void evictCollection(String arg0, Serializable arg1) throws HibernateException {
sessionFactory.evictCollection(arg0, arg1);
}
#Override
public void evictCollection(String arg0) throws HibernateException {
sessionFactory.evictCollection(arg0);
}
#Override
public void evictEntity(String arg0, Serializable arg1) throws HibernateException {
sessionFactory.evictEntity(arg0, arg1);
}
#Override
public void evictEntity(String arg0) throws HibernateException {
sessionFactory.evictEntity(arg0);
}
#Override
public void evictQueries() throws HibernateException {
sessionFactory.evictQueries();
}
#Override
public void evictQueries(String arg0) throws HibernateException {
sessionFactory.evictQueries(arg0);
}
#Override
public Map getAllClassMetadata() throws HibernateException {
return sessionFactory.getAllClassMetadata();
}
#Override
public Map getAllCollectionMetadata() throws HibernateException {
return sessionFactory.getAllCollectionMetadata();
}
#Override
public ClassMetadata getClassMetadata(Class arg0) throws HibernateException {
return sessionFactory.getClassMetadata(arg0);
}
#Override
public ClassMetadata getClassMetadata(String arg0) throws HibernateException {
return sessionFactory.getClassMetadata(arg0);
}
#Override
public CollectionMetadata getCollectionMetadata(String arg0) throws HibernateException {
return sessionFactory.getCollectionMetadata(arg0);
}
#Override
public Session getCurrentSession() throws HibernateException {
return sessionFactory.getCurrentSession();
}
#Override
public Set getDefinedFilterNames() {
return sessionFactory.getDefinedFilterNames();
}
#Override
public FilterDefinition getFilterDefinition(String arg0) throws HibernateException {
return sessionFactory.getFilterDefinition(arg0);
}
#Override
public Statistics getStatistics() {
return sessionFactory.getStatistics();
}
#Override
public boolean isClosed() {
return sessionFactory.isClosed();
}
#Override
public Session openSession() throws HibernateException {
return sessionFactory.openSession();
}
#Override
public StatelessSession openStatelessSession() {
return sessionFactory.openStatelessSession();
}
#Override
public StatelessSession openStatelessSession(Connection arg0) {
return sessionFactory.openStatelessSession(arg0);
}
#Override
public Reference getReference() throws NamingException {
return sessionFactory.getReference();
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
#Override
public String toString() {
return String.valueOf(sessionFactory.hashCode());
}
#Override
public boolean containsFetchProfileDefinition(String arg0) {
return sessionFactory.containsFetchProfileDefinition(arg0);
}
#Override
public Cache getCache() {
return sessionFactory.getCache();
}
#Override
public SessionFactoryOptions getSessionFactoryOptions() {
return sessionFactory.getSessionFactoryOptions();
}
#Override
public TypeHelper getTypeHelper() {
return sessionFactory.getTypeHelper();
}
#Override
public SessionBuilder withOptions() {
return sessionFactory.withOptions();
}
#Override
public StatelessSessionBuilder withStatelessOptions() {
return sessionFactory.withStatelessOptions();
}
}
My application context is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/disautomation"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<bean id="sessionFactory" class="com.practice.swh.entity.HRSessionFactory">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>
<bean id="mySessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="mappingResources">
<list>
<value>employee.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.generate_statistics">true</prop>
</props>
</property>
</bean>
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="find*" read-only="true" />
<tx:method name="get*" read-only="true" />
<tx:method name="executeQuery*" propagation="REQUIRES_NEW" rollback-for="Exception"/>
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.practice.swh.manager..*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut" />
</aop:config>
<bean id="employeeDao" class="com.practice.swh.dao.impl.EmployeeDaoImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean id="employeeManager" class="com.practice.swh.manager.impl.EmployeeManagerImpl">
<property name="employeeDao" ref="employeeDao"></property>
<property name="dummyManager" ref="dummyManager"></property>
</bean>
</beans>
Manager implementation:
package com.practice.swh.manager.impl;
import com.practice.swh.dao.EmployeeDao;
import com.practice.swh.entity.Employee;
import com.practice.swh.manager.EmployeeManager;
public class EmployeeManagerImpl implements EmployeeManager {
private EmployeeDao employeeDao;
#Override
public Employee getEmployee(Integer employeeId) {
Employee employee = employeeDao.getEmployee(employeeId);
//System.out.println(employee.getDepartment());
//System.out.println(employee.getAddresses());
return employee;
}
public EmployeeDao getEmployeeDao() {
return employeeDao;
}
public void setEmployeeDao(EmployeeDao employeeDao) {
this.employeeDao = employeeDao;
}
}
Dao Implementation:
package com.practice.swh.dao.impl;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import com.practice.swh.dao.EmployeeDao;
import com.practice.swh.entity.Employee;
public class EmployeeDaoImpl implements EmployeeDao {
private SessionFactory sessionFactory;
#Override
public Employee getEmployee(Integer employeeId) {
Session session = sessionFactory.getCurrentSession();
return (Employee) session.get(Employee.class, employeeId);
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
My test class :
package com.practice.swh.client;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.practice.swh.entity.Employee;
import com.practice.swh.manager.EmployeeManager;
public class EmployeeTest {
public static void main(String[] args) {
getEmployeeTest();
}
private static void getEmployeeTest() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
EmployeeManager employeeManager = (EmployeeManager) ctx.getBean("employeeManager");
Employee employee = employeeManager.getEmployee(4);
System.out.println(employee);
}
}
When I execute the test class, I get the following exception:
Exception in thread "main" org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:883)
at com.practice.swh.entity.HRSessionFactory.getCurrentSession(HRSessionFactory.java:100)
at com.practice.swh.dao.impl.EmployeeDaoImpl.getEmployee(EmployeeDaoImpl.java:34)
at com.practice.swh.manager.impl.EmployeeManagerImpl.getEmployee(EmployeeManagerImpl.java:47)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at com.sun.proxy.$Proxy6.getEmployee(Unknown Source)
at com.practice.swh.client.EmployeeTest.getEmployeeTest(EmployeeTest.java:35)
at com.practice.swh.client.EmployeeTest.main(EmployeeTest.java:12)
However, the code works fine when I change the application context to not use the custom session factory as below:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/disautomation"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- <bean id="sessionFactory" class="com.practice.swh.entity.HRSessionFactory">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean> -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="mappingResources">
<list>
<value>employee.hbm.xml</value>
<value>department.hbm.xml</value>
<value>employeeAddress.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.generate_statistics">true</prop>
</props>
</property>
</bean>
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="find*" read-only="true" />
<tx:method name="get*" read-only="true" />
<tx:method name="executeQuery*" propagation="REQUIRES_NEW" rollback-for="Exception"/>
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.practice.swh.manager..*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut" />
</aop:config>
<bean id="employeeDao" class="com.practice.swh.dao.impl.EmployeeDaoImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean id="employeeManager" class="com.practice.swh.manager.impl.EmployeeManagerImpl">
<property name="employeeDao" ref="employeeDao"></property>
<property name="dummyManager" ref="dummyManager"></property>
</bean>
</beans>
What is the issue if I use a custom SessionFactory implementation?

There are two issues in your code:
First. You have to use #Autowire annotation when injecting Spring beans to be able to use them properly.
Second. When you are using transaction manager with sessionFactory you should annotate service or dao method with #Transaction annotation
Try that and see if it helps

Related

Rollback not working in jdbc spring programatic transaction

Im unable to get a rollback working in my spring (3.0.5) jdbc application, running on Oracle 11.2
When I throw NoClassesException in the Controller below the row inserted by updatedB() remains in the dB.
I think this is because autoCommit is on (by default) in my dataSource so the commit has already happened and the rollback obviously doesn't work,
but I thought the Spring DataSourceTransactionManager handled all this and enforced the rollback?
Interestingly, when i turn autoCommit off in my dataSource ie comment in the :
"defaultAutoCommit" value="false"
and call the commit explicity myself ie comment in:
this.jdbcTemplate.getDataSource().getConnection().commit();
nothing happens ie the row is not commited at all,so it looks like i've done something stupid.
If someone could please point out this mistake I would be very gratefull
My code is :
public static void main(String[] args) {
String [] configList ={"database.xml","spring.xml"};
ApplicationContext ctx = new ClassPathXmlApplicationContext(configList);
cont = (Controller)ctx.getBean("controller");
cont.transactionTest();
}
// Controller , called from Main()
public class Controller {
private JdbcTemplate jdbcTemplate;
public void transactionTest()
{
int retCode=0;
try {
retCode = updatedB("param1","param2");
//this.jdbcTemplate.getDataSource().getConnection().commit();
throw new NoClassesException();
}catch (NoClassesException e){
System.out.println(e.getMessage() + "2 patents ");
}
}
public int updatedB(String param1,String param2 )
{
int stat = 0;
stat = this.jdbcTemplate.update("INSERT INTO myTable"
+ "(param1,param2)"
+ " VALUES(?,?)" ,
new Object[] { param1,param2});
return stat;
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
public class NoClassesException extends RuntimeException {
public NoClassesException() {
super("Rolled back ");
}
}
and my spring.xml file is:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean id="controller" class="Controller">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="transaction*" propagation="REQUIRED" rollback-for="NoClassesException" />
<tx:method name="update*" propagation="SUPPORTS" />
<tx:method name="*" propagation="SUPPORTS" read-only="true" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="myMethods" expression="execution(* *..Controller.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="myMethods" />
</aop:config>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
and my database.xml file is:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean id="dataConfigPropertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="searchSystemEnvironment" value="true" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="initialSize" value="2" />
<property name="maxActive" value="2" />
<property name="url" value="my connection details" />
<property name="username" value="xxx" />
<property name="password" value="xxx" />
<!-- <property name="defaultAutoCommit" value="false" /> -->
</bean>
</beans>
Your code should be updated such as
public void transactionTest()
{
int retCode=0;
retCode = updatedB("param1","param2");
//this.jdbcTemplate.getDataSource().getConnection().commit();
throw new NoClassesException();
}
public int updatedB(String param1,String param2 )
{
int stat = 0;
stat = this.jdbcTemplate.update("INSERT INTO myTable"
+ "(param1,param2)"
+ " VALUES(?,?)" ,
new Object[] { param1,param2});
return stat;
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}

Spring-Hibernate - No Session found for current thread

I have a java stuts2 web application using spring and hibernate.
Im getting org.hibernate.HibernateException: No Session found for current thread.
SpringBean.xml
<?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" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<context:component-scan base-package="org.rohith" />
<context:annotation-config />
<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/company" />
<property name="username" value="root" />
<property name="password" value="password" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>hibernate.cfg.xml</value>
</list>
</property>
</bean>
<!-- <tx:annotation-driven/> -->
<bean id = "transactionManager" class = "org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name = "sessionFactory" ref = "sessionFactory" />
</bean>
<bean id="customerDaoImpl" class="org.rohith.dao.impl.CustomerDaoImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="customerServiceImpl" class="org.rohith.service.impl.CustomerServiceImpl">
<property name="customerDaoImpl" ref="customerDaoImpl"/>
</bean>
</beans>
hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Names the annotated entity class -->
<mapping class="org.rohith.model.Customer"/>
</session-factory>
</hibernate-configuration>
CustomerServiceImpl.java
package org.rohith.service.impl;
import org.rohith.dao.impl.CustomerDaoImpl;
import org.rohith.model.Customer;
import org.rohith.service.CustomerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class CustomerServiceImpl implements CustomerService {
#Autowired
private CustomerDaoImpl customerDaoImpl;
#Override
public void saveCustomer(Customer customer) {
customerDaoImpl.saveCustomer(customer);
}
public CustomerDaoImpl getCustomerDaoImpl() {
return customerDaoImpl;
}
public void setCustomerDaoImpl(CustomerDaoImpl customerDaoImpl) {
this.customerDaoImpl = customerDaoImpl;
}
}
CustomerDaoImpl.java
package org.rohith.dao.impl;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.rohith.dao.CustomerDao;
import org.rohith.model.Customer;
public class CustomerDaoImpl implements CustomerDao {
private SessionFactory sessionFactory;
#Override
public void saveCustomer(Customer customer) {
Session session = getSession();
session.clear();
try {
session.saveOrUpdate(customer);
session.flush();
} catch (Throwable e) {
throw new RuntimeException(e.getMessage(), e);
}
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public SessionFactory getSessionFactory() {
return this.sessionFactory;
}
public Session getSession() throws HibernateException {
Session sess = getSessionFactory().getCurrentSession();
if (sess == null) {
sess = getSessionFactory().openSession();
}
// Session sess = getSessionFactory().openSession();
return sess;
}
}
CustomerAction.java
public class CustomerAction extends ActionSupport{
private String name;
private String addr1;
private String addr2;
private String city;
private String state;
private CustomerServiceImpl customerServiceImpl;
//Getters and setters
public String execute(){
Customer cust= new Customer();
cust.setName(name);
cust.setAddress1(addr1);
cust.setAddress2(addr2);
cust.setCity(city);
cust.setState(state);
System.out.println(name);
WebApplicationContext webApplicationContext = WebApplicationContextUtils
.getRequiredWebApplicationContext(getRequest().getSession()
.getServletContext());
customerServiceImpl = (CustomerServiceImpl) webApplicationContext.getBean("customerServiceImpl");
customerServiceImpl.saveCustomer(cust);
//saveCust(cust);
return "success";
}
protected HttpServletRequest getRequest() {
return ServletActionContext.getRequest();
}
protected HttpServletResponse getResponse() {
return ServletActionContext.getResponse();
}
}
The Exception I am getting
org.hibernate.HibernateException: No Session found for current thread
org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:978)
org.rohith.dao.impl.CustomerDaoImpl.getSession(CustomerDaoImpl.java:33)
org.rohith.dao.impl.CustomerDaoImpl.saveCustomer(CustomerDaoImpl.java:16)
org.rohith.service.impl.CustomerServiceImpl.saveCustomer(CustomerServiceImpl.java:18)
org.rohith.CustomerAction.execute(CustomerAction.java:36)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:606)
You have a transaction manager specified in your Spring config, but no configuration on when or where to apply transactions.
In your SpringBean.xml you should uncomment <tx:annotation-driven/>:
<tx:annotation-driven transaction-manager="transactionManager"/>
And then you should annotate the CustomerServiceImpl.saveCustomer method as #Transactional:
#Service
public class CustomerServiceImpl implements CustomerService {
...
#Override
#Transactional
public void saveCustomer(Customer customer) {
customerDaoImpl.saveCustomer(customer);
}
...
}
Add the following property in your hibernate.cfg.xml file for Hibernate 4.
<property name="hibernate.current_session_context_class">thread</property>
Add #EnableTransactionManagement annotation in your java configuration file if your configuration based on annotation without xml.
This may help someone
You can add in hibernate.proerties below value. It's worked for me.
hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext
or
hibernate.current_session_context_class=thread

Can we use sessionFactory multiple times which provided by spring?

but in my code i'm getting null pointer exception when i'm using session factory for second time . and it is working fine in first .
here is my code
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
<property name="url" value="jdbc:mysql://localhost:3306/pdevice"></property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="show_sql">true</prop>
<prop key="dialect">org.hibernate.dialect.MySQL5Dialect</prop>
</props>
</property>
<property name="mappingResources">
<array>
<value>/LoginDTO.hbm.xml</value>
</array>
</property>
</bean>
<bean id="loginDAO" class="com.raj.sprmvc.dao.LoginDAOImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean id="loginManager" class="com.raj.sprmvc.manager.LoginManagerImpl">
<property name="loginDAO" ref="loginDAO"></property>
</bean>
<!-- <bean id="login" class="com.raj.sprmvc.controller.LoginController">
<property name="loginManager" ref="loginManager"></property> </bean> -->
<bean id="commandController" name="/login.do" class="com.raj.sprmvc.controller.LoginController">
<property name="loginManager" ref="loginManager"></property>
<property name="commandClass" value="com.raj.sprmvc.dto.LoginDTO"></property>
<property name="validator" ref="loginValidator"></property>
</bean>
<bean id="loginValidator" class="com.raj.sprmvc.validator.LoginValidator"></bean>
<!-- ++++++++++++++++++++++to update place+++++++++++++++++++++ -->
<bean id="updateUNDAO" class="com.raj.sprmvc.dao.UpdateUNDAOImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean id="updateManager" class="com.raj.sprmvc.manager.UpdateManagerImpl">
<property name="undao" ref="updateUNDAO"></property>
</bean>
<bean id="commandController1" name="/update.do"
class="com.raj.sprmvc.controller.UpdateController">
<property name="updateManager" ref="updateManager"></property>
<property name="commandClass" value="com.raj.sprmvc.dto.LoginDTO"></property>
<!-- <property name="validator" ref="loginValidator"></property> -->
</bean>
when i'm trying to use sessinfactory for second time it is giving nullpointer ..i know this basic concept but struggling to solve this pls share .......
thanks
this is the first module
public class LoginDAOImpl implements LoginDAO{
private SessionFactory sessionFactory;
#Override
public boolean isExist(LoginDTO ldto) {
Session session=sessionFactory.openSession();
Query query=session.createQuery(" FROM LoginDTO WHERE username='"+ldto.getUsername()+"' AND password='"+ldto.getPassword()+"'");
if(query.uniqueResult()!=null){
return true;
}
return false;
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
and in second module
public class UpdateUNDAOImpl implements UpdateUNDAO{
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public void update(LoginDTO ldto){
Session session=sessionFactory.openSession();
System.out.println(session);
Transaction tr= session.beginTransaction();
tr.begin();
LoginDTO ldto1=(LoginDTO)session.load(LoginDTO.class, 1);
ldto1.setPlace(ldto.getPlace());
session.update(ldto1);
tr.commit();
session.close();
}
}
in this module the line Session session=sessionFactory.openSession(); is giving null pointer exception
exception
exception
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:659)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:563)
javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
note The full stack trace of the root cause is available in the Apache Tomcat/7.0.27 logs.
exception

Hibernate transaction not working

I have a really strange problem.I wrote an application which is using spring+hibernate. my hibernate configurations is like below:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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-2.0.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="placeholderPrefix" value="${hospital_"/>
<property name="location" value="hospital.properties"/>
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${hospital_hibernate.driverClassName}"/>
<property name="jdbcUrl" value="${hospital_hibernate.url}"/>
<property name="user" value="${hospital_hibernate.username}"/>
<property name="password" value="${hospital_hibernate.password}"/>
<!--
<property name="acquireIncrement" value="20"/>
<property name="acquireRetryAttempts" value="30"/>
<property name="acquireRetryDelay" value="1000"/>
<property name="autoCommitOnClose" value="true"/>
<property name="checkoutTimeout" value="10000"/>
<property name="debugUnreturnedConnectionStackTraces" value="true"/>
<property name="idleConnectionTestPeriod" value="100"/>
<property name="initialPoolSize" value="1"/>
<property name="maxConnectionAge" value="1000"/>
<property name="maxConnectionAge" value="1000000"/>
<property name="maxIdleTime" value="200"/>
<property name="maxIdleTimeExcessConnections" value="3600"/>
<property name="maxPoolSize" value="10"/>
<property name="minPoolSize" value="1"/>
<property name="preferredTestQuery" value="select 1"/>
<property name="testConnectionOnCheckin" value="false"/>
<property name="unreturnedConnectionTimeout" value="1000"/>
-->
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="schemaUpdate" value="${hospital_schema.update}"/>
<property name="mappingResources">
<list>
<value>com/saman/entity/hbms/Employee.hbm.xml</value>
<value>com/saman/entity/hbms/Shift.hbm.xml</value>
<value>com/saman/entity/hbms/Patient.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hospital_hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hospital_hibernate.showsql}</prop>
<!--<prop key="hibernate.hbm2ddl.auto">update</prop>-->
<prop key="hibernate.generate_statistics">true</prop>
<!--<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.SingletonEhCacheRegionFactory</prop>-->
<!--<prop key="net.sf.ehcache.configurationResourceName">ehcache.xml</prop>-->
<prop key="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</prop>
<prop key="hibernate.use_sql_comments">true</prop>
<prop key="hibernate.transaction.auto_close_session">true</prop>
</props>
</property>
<property name="eventListeners">
<map>
<entry key="merge">
<bean class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/>
</entry>
</map>
</property>
</bean>
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
<!--<property name="prepareConnection" value="true"/>-->
<!--<property name="hibernateManagedSession" value="true"/>-->
</bean>
</beans>
and I also set my tx:advice like below:
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" propagation="REQUIRED" read-only="true"/>
<tx:method name="*" rollback-for="java.lang.Throwable"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="transactionServiceOperation"
expression="execution(* com.saman.svc.dalc.IEmployeeDA.*(..))"/>
<aop:pointcut id="transactionServiceOperation2"
expression="execution(* com.saman.svc.dalc.IPatientDA.*(..))" />
<aop:pointcut id="transactionServiceOperation3"
expression="execution(* com.saman.svc.dalc.IShiftDA.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="transactionServiceOperation"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="transactionServiceOperation2"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="transactionServiceOperation3"/>
</aop:config>
the problem here is that when i run my application, for the 10 or 11 database accesses it works fine, but after that, it seems like that my applications get locked and doesn't respond.
I really don't know where is the problem.
p.s. I define all my DAs in patientDA, shiftDA, and employeeDA classes which inherits IPatientDA, IShiftD, and IEmployeeDA.
my GenericDA:
public class GenericDA<TEntity, TId extends Serializable> extends HibernateDaoSupport implements IGenericDA<TEntity, TId>
{
private Boolean isDateString = false;
private Dialect mappingDialect = Dialect.mysql;
public Boolean isDateString()
{
return isDateString;
}
public void setDateString(Boolean dateString)
{
isDateString = dateString == null ? false : dateString;
}
public Dialect getMappingDialect()
{
return mappingDialect;
}
public Dialect dialect()
{
return this.getMappingDialect();
}
public void setMappingDialect(Dialect mappingDialect)
{
this.mappingDialect = mappingDialect;
}
public Class getType()
{
Type tClass = null;
Type type = this.getClass().getGenericSuperclass();
if (type instanceof ParameterizedType)
{
ParameterizedType paramType = (ParameterizedType) type;
tClass = paramType.getActualTypeArguments()[0];
}
return (Class) tClass;
}
public String getStringType()
{
return this.getType().getName();
}
public TEntity get(TId id)
{
return (TEntity) this.getSession().get(getType(), id);
}
public List<TEntity> get()
{
return (List<TEntity>) this.getSession().createCriteria(getType()).list();
}
public List<TEntity> get(long from, long size)
{
return this.getSession().createCriteria(getType())
.setFirstResult((int) from)
.setMaxResults((int) size)
.list();
}
public TEntity insert(TEntity entity)
{
this.getSession().save(entity);
return entity;
}
public TEntity update(TEntity entity)
{
try
{
this.getSession().evict(entity);
this.getSession().update(entity);
//this.getSession().flush();
}
catch (HibernateException ex)
{
this.getSession().evict(entity);
this.getSession().clear();
// this.getSession().update(entity);
throw ex;
}
return entity;
}
public void delete(TId id)
{
this.getSession().delete(get(id));
}
public void delete(TEntity entity)
{
this.getSession().delete(entity);
}
public List<TEntity> get(int from, int size)
{
//noinspection unchecked
return this.getSession().createCriteria(getType())
.setFirstResult(from)
.setMaxResults(size)
.list();
}
public long getCount()
{
return (Long) this.getSession().createQuery("select count(entity.id) from " + getStringType() + " entity")
.uniqueResult();
}
public Object getProperty(Long id, String property)
{
Criteria criteria = this.getSession().createCriteria(getType());
criteria.add(Restrictions.eq("id", id));
criteria.setProjection(Projections.property(property));
criteria.setMaxResults(1);
return criteria.uniqueResult();
}
public org.hibernate.Session prepareFilteredSession(Date effectiveDate)
{
org.hibernate.Session session = this.getSession();
if (effectiveDate != null)
session.enableFilter("effectiveDate").setParameter("fDate", effectiveDate);
return session;
}
public void DisableFilter(org.hibernate.Session session)
{
session.disableFilter("effectiveDate");
}
public String getLikeExpression(String filter, String parameter)
{
String result = "LIKE";
if (filter.startsWith("*"))
{
if (this.mappingDialect.equals(Dialect.oracle))
result += " '%' ||";
else
result += " '%' +";
}
result += " :" + parameter + " ";
if (filter.endsWith("*"))
{
if (this.mappingDialect.equals(Dialect.oracle))
result += " || '%'";
else
result += " + '%'";
}
return result;
}
public String getLikeParameter(String parameter)
{
if (parameter.startsWith("*"))
parameter = parameter.substring(1);
if (parameter.endsWith("*"))
parameter = parameter.substring(0, parameter.length() - 1);
return parameter;
}
public Query setDateParameter(Query query, String name, Date value)
{
if (this.isDateString)
return query.setString(name, String.format("%1$tY-%1$tm-%1$td %tT", value));
else
return query.setParameter(name, value);
}
}
and for example my ShiftDA example is:
public class ShiftDA extends GenericDA<ShiftEntity, Long> implements IShiftDA {
public void updateNumberOfPatients( int numberOfPatients, Long columnID ){
try{
Statement st = this.getSession().connection().createStatement();
String sql = "UPDATE shift SET CurrentNumberOfPatients='" + numberOfPatients + "' WHERE ShiftId='" + columnID.toString() + "' ";
st.executeUpdate(sql);
}catch( Exception e ){
e.printStackTrace();
}
}
}
Judging by these C3P0 settings (min =1 max = 10) and the 10 or 11 requests you have specified I'd take a guess and say that you are exhausting the connection pool because something isn't releasing them. I suspect this is related to the tx-manager and it not knowing when the session's life is over.
Also - I would use commons DBCP rather than C3P0.
Can you post what the DA objects are doing?

Spring, Hibernate, transaction management, not committed

So, I try to use Spring for transaction management. Finally my application had worked, but deleting do not commits. Before using Spring I managed transactions in DAO, and I thought that after I can remove this code. But now deleting do not commit to DB.
My DAO:
protected Session getSession() {
Session session = sessionFactory.openSession();
ThreadLocalSessionContext.bind(session);
return session;
}
public void delete(T t) {
Session session = getSession();
// **this approach I used before**
// session.beginTransaction();
// try {
// session.delete(t);
// session.getTransaction().commit();
// } catch (Exception e) {
// session.getTransaction().rollback();
// }
session.delete(t);
}
My applicationContext:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation=" http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://ngs-java-srv.synapse.com:3306/mybase" />
<property name="username" value="user" />
<property name="password" value="password" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- <property name="configLocation" value="hibernate.cfg.xml" /> -->
<property name="packagesToScan" value="todolist.entity" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<!-- dao beans -->
<bean id="userDao"
class="todolist.dao.hibernate.UserDaoImpl">
<constructor-arg>
<value>todolist.entity.User</value>
</constructor-arg>
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="itemDao"
class="todolist.dao.hibernate.ItemDaoImpl">
<constructor-arg>
<value>todolist.entity.Item</value>
</constructor-arg>
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- service bean -->
<bean id="userService" class="todolist.service.UserServiceImpl">
<property name="userDao" ref="userDao" />
<property name="itemDao" ref="itemDao" />
</bean>
<!-- transaction manager -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" mode="aspectj"/>
<!-- <tx:annotation-driven/> -->
<!-- <aop:config>
<aop:pointcut id="serviceMethods"
expression="execution(* todolist.service.UserService.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRES_NEW" />
<tx:method name="deleteItem" no-rollback-for="Exception" />
</tx:attributes>
</tx:advice> -->
<!-- backbeans -->
<bean id="userLogin" class="todolist.jsf.UserLogin"
scope="request">
<property name="userService" ref="userService" />
</bean>
<bean id="userLogged" class="todolist.jsf.UserLogged"
scope="session">
<aop:scoped-proxy />
</bean>
<bean id="userRegister" class="todolist.jsf.UserRegister"
scope="request">
<property name="userService" ref="userService" />
</bean>
<bean id="createItem" class="todolist.jsf.CreateItem"
scope="request">
<property name="userService" ref="userService" />
</bean>
<bean id="todoList" class="todolist.jsf.TodoList"
scope="request">
<property name="userService" ref="userService" />
</bean>
</beans>
UserServiceImpl class
package todolist.service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import todolist.exception.AuthorizationError;
import todolist.exception.DuplicateLoginsException;
import todolist.service.StringToHashTool;
import todolist.dao.ItemDao;
import todolist.dao.UserDao;
import todolist.entity.Item;
import todolist.entity.User;
public class UserServiceImpl implements UserService {
//private static final Logger log = Logger.getLogger(UserServiceImpl.class);
private UserDao userDao;
private ItemDao itemDao;
public void setItemDao(ItemDao itemDao) {
this.itemDao = itemDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
#Override
#Transactional(propagation = Propagation.REQUIRES_NEW)
public boolean isUserExists(String login) {
return (userDao.getUserByLogin(login) != null);
}
#Override
#Transactional(propagation = Propagation.REQUIRES_NEW)
public boolean isPasswordCorrect(String login, String password) {
if (isUserExists(login)) {
return userDao.getUserByLogin(login).getPassword()
.equals(StringToHashTool.getHash(password));
} else {
return false;
}
}
#Override
#Transactional(propagation = Propagation.REQUIRES_NEW)
public User login(String login, String password) {
if (isPasswordCorrect(login, password)) {
return userDao.getUserByLogin(login);
} else {
throw new AuthorizationError("Incorrect password");
}
}
#Override
#Transactional(propagation = Propagation.REQUIRES_NEW)
public boolean register(String login, String password) {
if (isUserExists(login)) {
throw new DuplicateLoginsException("Login " + login + " is already used.");
} else {
User user = new User();
user.setLogin(login);
user.setPassword(StringToHashTool.getHash(password));
userDao.save(user);
return true;
}
}
#Override
#Transactional(propagation = Propagation.REQUIRES_NEW)
public void logout() {
}
#Override
#Transactional(propagation = Propagation.REQUIRES_NEW)
public Item createItem(Long creator_id, Long performer_id,
String description, Date dueDate) {
Item item = new Item();
User user = userDao.getById(creator_id);
item.setCreator(user);
user = userDao.getById(performer_id);
item.setPerformer(user);
item.setDescription(description);
item.setStartDate(new Date());
item.setDueDate(dueDate);
itemDao.save(item);
return item;
}
#Override
#Transactional(propagation = Propagation.REQUIRES_NEW)
public void deleteItem(Long item_id) {
Item item = itemDao.getById(item_id);
itemDao.delete(item);
}
#Override
#Transactional(propagation = Propagation.REQUIRES_NEW)
public List<Item> getUserItems(String login) {
User user = userDao.getUserByLogin(login);
return itemDao.getItemsByPerformer(user.getId());
}
#Override
#Transactional(propagation = Propagation.REQUIRES_NEW)
public List<User> getUsers() {
return userDao.getUsers();
}
}
<aop:pointcut
id="serviceMethods"
expression="execution(*todolist.service.UserService.*(..))"
/>
First Step:
Change this to:
<aop:pointcut
id="serviceMethods"
expression="todolist.service.UserServiceImpl.delete()"
/>
See if delete's start committing. I just want to make sure you flush out any typos and what have you. If this explicit config fails then there must be something wrong with the config.
I have had success using the Spring HibernateTransactionManager object and annotation driven configuration. In my application-context, I simply declare the following two beans:
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="session_factory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
Then in my service layer, your UserServiceImpl for example:
public class UserServiceImpl implements UserService {
private final UserDao userDao;
private final ItemDao itemDao;
public UserServiceImpl(UserDao userDao, ItemDao itemDao) {
this.userDao = userDao;
this.itemDao = itemDao;
}
#Override
#Transactional(propagation = Propagation.REQUIRES_NEW)
public boolean isUserExists(String login) {
return (userDao.getUserByLogin(login) != null);
}
...
It's important to move you transaction annotations as close to the view (in MVC) as possible. The reason is 1) performance and 2) atomic transactions. If the call calling the UserService calls the isUserExists, isPasswordCorrect and login methods in a single function call, you would want those to execute in a single transaction. To do so, remove the #Transactional annotation from the UserServiceImpl and move it to the calling class. This ensures that a single transaction is used for all three method calls. For atomic execution, this also works. Think of the classic bank money transfer example. If you had two separate transactions on the UserService, the first two method call can succeed and the last one fail. The firt two transactions would be committed because they are in separate transaction blocks which would leave you database in an inconsistent state. Of course, atomic transactions are mostly relevant for transactions that write data.
Also, don't add the transactional annotations to the interfaces, keep them on the implementations.
Then in my DAO, I simply do a sessionFactory.getCurrentSession() and go from there. getCurrentSession() is thread safe but keep it private to your DAOs.
Use getCurrentSession instead of openSession in your DAO, so that the getSession method looks like:
protected Session getSession() {
return sessionFactory.getCurrentSession();
}
You're creating a new session that uses a different database connection so the transaction set up for the service doesn't apply.
Also as you have them configured the DAOs will have a default scope of singleton; passing an entity as a constructor-argument doesn't make sense. A singleton shouldn't have instance state specific to some individual transaction.

Categories

Resources