Spring-Hibernate - No Session found for current thread - java

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

Related

Deadlock caused by EntityManager using dependency injection

I am developing an application with REST services. I am using dependency injection to, among other things, inject EntityManagerFactory. I have a heavy process where I want to use threads, but it is giving me a deadlock when using EntityManager. The code:
Note: All code has been simplified and renamed classes to explain the problem
persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="mypersistenceunit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!-- Entities -->
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.event.merge.entity_copy_observer" value="allow" />
<property name="hibernate.connection.autocommit" value="false"/>
</properties>
</persistence-unit>
</persistence>
applicationContext.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
"
default-autowire="byName">
<context:property-placeholder location="classpath:database.properties"/>
<bean id="logDao" class="my.package.example.dao.LogDao">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="extractDataDao" class="my.package.example.source.ExtractDataDao">
<property name="completeDatabaseModel" ref="completeDatabaseModel"/>
</bean>
<bean id="completeDatabaseModel" class="my.package.example.source.CompleteDatabaseModel">
<property name="logDao" ref="logDao" />
</bean>
<bean id="fill" class="my.package.example.services.impl.FillDatabaseServiceImpl">
<property name="extractDataDao" ref="extractDataDao" />
</bean>
<!-- Configuracion de acceso a base de datos -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="persistenceUnitName" value="mypersistenceunit"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
</bean>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
</bean>
<bean id="myDataSource" parent="dataSource">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
FillDatabaseServiceImpl.java:
public class FillDatabaseServiceImpl implements FillDatabaseService {
private ExtractDataDao extractDataDao;
private final static Gson gson = new Gson();
#Override
public Response start() {
ResultDto resultDto = new ResultDto();
Thread thread = new Thread(this.extractDataDao);
thread.start();
resultDto.setData("Process has started");
return Response.ok(gson.toJson(resultDto)).build();
}
public void setExtractDataDao(ExtractDataDao extractDataDao) {
this.extractDataDao = extractDataDao;
}
}
ExtractDataDao.java:
public class ExtractDataDao implements Runnable {
private CompleteDatabaseModel completeDatabaseModel;
#Override
public void run() {
// Very simplifed class
int numThreads = 5;
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
for (int j = 0; j < numThreads; j++) {
executor.execute(this.completeDatabaseModel);
}
}
public void setCompleteDatabaseModel(CompleteDatabaseModel completeDatabaseModel) {
this.completeDatabaseModel = completeDatabaseModel;
}
}
CompleteDatabaseModel.java
public class CompleteDatabaseModel implements Runnable {
private EntityManagerFactory entityManagerFactory;
private LogDao logDao;
#Override
public void run() {
// Very simplified class
EntityManager entityManager = null;
try {
entityManager = this.entityManagerFactory.createEntityManager();
...
this.logDao.insertLog("Test message", CATEGORY);
...
this.getCountry(entityManager, "country")
} finally {
entityManager.close();
}
}
private synchronized Country getCountry(final EntityManager entityManager, String strCountry) {
Country country = Country.getCountryByCountry(entityManager, strCountry);
if (country == null) {
country = ImdbToMovieDatabase.convert(strCountry, Country.class);
entityManager.getTransaction().begin();
entityManager.persist(country);
entityManager.getTransaction().commit();
country = Country.getCountryByCountry(entityManager, strCountry);
}
return country;
}
public void setLogDao(final LogDao logDao) {
this.logDao = logDao;
}
}
And the classes that provoke deadlock:
LogDao.java:
public class LogDao {
private EntityManagerFactory entityManagerFactory;
public void insertLog(final String message, final Category.CategoryName categoryName) {
Log log = new Log();
EntityManager entityManager = this.entityManagerFactory.createEntityManager();
try {
entityManager.getTransaction().begin();
Category category = Category.getCategoryByName(entityManager, categoryName.name());
log.setCategory(category);
log.setLog(message);
entityManager.persist(log); // // Cause of deadlock in Thread-1 (for example)
entityManager.getTransaction().commit();
} catch (Exception e) {
logger.error("Error persisting log [" + message + "]", e);
entityManager.getTransaction().rollback();
} finally {
if (entityManager != null) {
entityManager.close();
}
}
}
public void setEntityManagerFactory(final EntityManagerFactory entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
}
}
Entity.java:
public static Country getCountryByCountry(final EntityManager entityManager, final String strCountry) {
Country country = null;
try {
TypedQuery<Country> typedQuery =
entityManager.createQuery(
"SELECT c FROM Country c WHERE country = ?",
Country.class);
typedQuery.setParameter(1, strCountry);
country = typedQuery.getSingleResult(); // Cause of deadlock in Thread-2 (for example)
} catch (NoResultException e) {
System.out.println("No data found for " + strCountry);
} catch (Exception e) {
e.printStackTrace();
}
return country;
}
Maybe private synchronized Country getCountry is provoking the deadlock? I don't think I should, since logDao has injected its own EntityManagerFactory
Can I use a connection pool?
Thanks in advance.

Exception when using custom session factory implementation

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

Null pointer error while using sessionfactory on Hibernate 4 with Spring 3.2

I'm struggling to figure out the exact problem, why the Null Pointer Error is thrown for Hibernate sessionFactory when I try to Auto wire sessionFactory from spring bean xml. Could somebody please help me out fix this. I'm new to Spring and deploying the app on Jboss server
Here is the Spring-Config.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
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.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<context:annotation-config />
<context:component-scan base-package="org.kp.db.dao.impl" />
<bean id="myDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/ebm" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="configLocation" value="classpath:/hibernate.cfg.xml" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
</beans>
Here is Hiberante.cfg.xml which I placed in webcontent folder
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<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/ebm</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<mapping resource="org/kp/db/model/Actioncode.hbm.xml"/>
<mapping class="org.kp.db.model.TblEBMFieldDetails"/>
<mapping class="org.kp.db.model.TbleOLI"/>
</session-factory>
</hibernate-configuration>
And the DAO class in which I'm trying to access the sessionFactory is
package org.kp.db.dao.impl;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.kp.db.dao.ActionCodeDao;
import org.kp.db.model.Actioncode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
/**
*
* #author Administrator
*/
#Repository
public class ActionCodeDaoImpl implements ActionCodeDao{
#Override
public String[] getActionCodes() {
throw new UnsupportedOperationException("Not supported yet.");
}
#Autowired(required=true)
SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
#Override
#Transactional(readOnly=true,propagation=Propagation.REQUIRED)
public String getActionCode(int id) {
//ApplicationContext context;
Session session = sessionFactory.getCurrentSession();
Actioncode actionCode=null;
actionCode = (Actioncode)session.get(Actioncode.class, 1);
return actionCode.getActionName();
}
}
#Named ("kpAction")
public class Actions {
public String getActionCode() {
ActionCodeDao action =new ActionCodeDaoImpl();
String str = action.getActionCode(1); System.out.println(str); return str;
}
}
When you run this line of code: ActionCodeDao action =new ActionCodeDaoImpl(); you get an object that is not managed by Spring and therefore will not contain the autowired dependencies.
I would say that is why you saw the null pointer.
However you say you have fixed it now, not sure if you inadvertantly changed this as well, if not im not sure how youve fixed it :)
I've fixed the issue, instead of accessing the object I used the getter method and it worked, not sure what is the real concept behind it.
public String getActionCode(int id) {
//ApplicationContext context;
Session session = getSessionFactory().getCurrentSession();
Actioncode actionCode=null;
actionCode = (Actioncode)session.get(Actioncode.class, 1);
return actionCode.getActionName();
}

Spring 3.2 and Hibernate 4 - Getting NullPointerException due to SessionFactory being null

I'm trying to convert my very small app to Spring 3.2 and Hibernate 4, but I can't get it to run properly with sessions. Some info below this paragraph, but ultimately the sessionFactory is always null everytime it gets to the DAO and I can't figure out why.
Comparing the console to Hibernate 3, Hibernate 3 shows this upon startup:Nov 23, 2012 10:51:52 PM org.springframework.orm.hibernate3.LocalSessionFactoryBean buildSessionFactory
INFO: Building new Hibernate SessionFactory
Stack trace:
java.lang.NullPointerException
dao.CSSDAOImpl.selectAllCSS(CSSDAOImpl.java:21)
hibernate-cfg.xml
<?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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean id="myDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.apache.derby.jdbc.EmbeddedDriver"></property>
<property name="url" value="jdbc:derby:C:\Users\Steven\MyDB"></property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="packagesToScan" value="net.form" />
<property name="dataSource" ref="myDataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.DerbyTenSevenDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<value>net.form.StyleChooser</value>
</list>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="CSSDAO" class="dao.CSSDAOImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
DAO:
package dao;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import net.form.StyleChooser;
public class CSSDAOImpl implements CSSDAO {
private SessionFactory sessionFactory;
#Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
#Transactional
public List selectAllCSS() {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
List l = session.createCriteria(StyleChooser.class).list();
session.flush();
tx.commit();
return l;
}
#Transactional
public StyleChooser selectCSSById(Integer ID) {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
StyleChooser sc = (StyleChooser) session.get(StyleChooser.class, ID);
session.flush();
tx.commit();
return sc;
}
#Transactional
public Integer insertCSS(StyleChooser insertCSS) {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Integer id = (Integer) session.save(insertCSS);
session.flush();
tx.commit();
return id;
}
#Transactional
public void deleteCSS(Integer CSSId) {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
StyleChooser sc = (StyleChooser) session.get(StyleChooser.class, CSSId);
session.delete(sc);
session.flush();
tx.commit();
}
#Transactional
public void updateCSS(StyleChooser cssWithNewValues) {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.update(cssWithNewValues);
session.flush();
tx.commit();
}
}
Accessing DAO...
package net.controllers;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import net.form.StyleChooser;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
import dao.CSSDAOImpl;
#Controller
#RequestMapping("/stylechoosertable.html")
public class IndexController extends MultiActionController {
Resource resource = new FileSystemResource(
"C:/Users/Steven/Desktop/Programming/workspace/CSSGeneratorHibernate4/WebContent/WEB-INF/hibernate.cfg.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
CSSDAOImpl dao = (CSSDAOImpl) beanFactory.getBean("CSSDAO");
#RequestMapping(method = RequestMethod.GET)
public ModelAndView showIndex(HttpServletRequest request) throws Exception {
List<StyleChooser> styleChooser = dao.selectAllCSS();
return new ModelAndView("stylechoosertable", "styleChooser", styleChooser);
}
}
In your Spring configuration file make the following change:
<bean id="CSSDAO" class="dao.CSSDAOImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
Now, in CSSDAOImpl remove all the static modifiers:
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
That should fix the NPE!
To keep things nice and clean you should use #Transactional-Annotation in all methods and not open the sessions manually but always with sessionFactory.getCurrentSession(). ...
I suppose you wanted to to do it that way anyways since you use tx: annotation-driven and have already imported the annotation.
Alternatively to Muel's answer, you could also use a #Autowired-Annotation on the setSessionFactory()-method.

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