Reputation: 13844
I was trying to do generic way of implementation of DAO and I followed as per the Article
Following are my genericDaoImpl class
@SuppressWarnings("unchecked")
@Repository
public abstract class GenericDaoImpl<E, K extends Serializable>
implements GenericDao<E, K> {
@Autowired
private SessionFactory sessionFactory;
protected Class<? extends E> daoType;
/**
* By defining this class as abstract, we prevent Spring from creating
* instance of this class If not defined as abstract,
* getClass().getGenericSuperClass() would return Object. There would be
* exception because Object class does not hava constructor with parameters.
*/
public GenericDaoImpl() {
Type t = getClass().getGenericSuperclass();
ParameterizedType pt = (ParameterizedType) t;
daoType = (Class) pt.getActualTypeArguments()[0];
}
protected Session currentSession() {
return sessionFactory.getCurrentSession();
}
@Override
public void add(E entity) {
currentSession().save(entity);
}
@Override
public void saveOrUpdate(E entity) {
currentSession().saveOrUpdate(entity);
}
@Override
public void update(E entity) {
currentSession().saveOrUpdate(entity);
}
@Override
public void remove(E entity) {
currentSession().delete(entity);
}
@Override
public E find(K key) {
return (E) currentSession().get(daoType, key);
}
@Override
public List<E> getAll() {
return currentSession().createCriteria(daoType).list();
}
}
GENERICDAO
public interface GenericDao<E,K> {
public void add(E entity) ;
public void saveOrUpdate(E entity) ;
public void update(E entity) ;
public void remove(E entity);
public E find(K key);
public List<E> getAll() ;
}
SERVICE CLASS
@Service
public class test {
@Autowired
TestPlanDao testPlanDao;
@Transactional(propagation = Propagation.REQUIRED)
public int saveTestPlan()
{
try
{
TestPlan tp=new TestPlan();
tp.setTestplan_version(1);
testPlanDao.saveTestPlan(tp);
logger.info("testplan saved");
return 1;
}
catch(Exception e)
{
e.printStackTrace();
logger.error(e.getMessage(),e);
return 0;
}
}
This is my daoImpl
@Repository
public class TestPlanDaoImpl extends GenericDaoImpl<TestPlan, Integer> implements TestPlanDao{
@Override
@Transactional
public void saveTestPlan(TestPlan tp) {
// TODO Auto-generated method stub
add(tp);
}
hibernate configuration xml
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://${mysqlHost}/${mysqldatabase}" />
<property name="username" value="${mysqlUserName}" />
<property name="password" value="${mysqlPassword}" />
<property name="removeAbandoned" value="true" />
<property name="initialSize" value="20" />
<property name="maxActive" value="30" />
<property name="maxIdle" value="-1" />
<property name ="testOnBorrow" value="true"/>
<property name ="validationQuery" value="SELECT 1"/>
</bean>
<bean id="sessionFactoryConf"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.test.model.TestPlan</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.transaction.auto_close_session">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
I am not able to find the cause of
org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:106)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:988)
Upvotes: 11
Views: 3788
Reputation: 695
you need to add following code in your hibernate configuration xml file
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<!-- property should be wired with a Hibernate SessionFactory in your case it is sessionFactoryConf -->
<property name="sessionFactory" ref="sessionFactoryConf" />
</bean>
Upvotes: 6
Reputation: 23
This happens when you try to save changes on a Business Object after a transaction has already finished.
I think you should take a look to Spring Data JPA ? It has a lot more to offer than a generic DAO.
Upvotes: 1
Reputation: 11
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactoryConf" />
</bean>
Upvotes: 1
Reputation: 161
Remove @Transactional annotation from function and use it on the class level.
Upvotes: 2
Reputation: 31
You have to remove the @Transactional annotation from the Repository method , use only the @Transactional annotation on the service layer method.
@Repository
public class TestPlanDaoImpl extends GenericDaoImpl<TestPlan, Integer> implements TestPlanDao{
@Override
@Transactional //Remove annotation from here
public void saveTestPlan(TestPlan tp) {
// TODO Auto-generated method stub
add(tp);
}
Upvotes: 3
Reputation: 1138
Did you try removing the following property :
<prop key="hibernate.transaction.auto_close_session">true</prop>
I believe that Hibernate will close the session too soon and resulting in your error. Since you use Spring TransactionManager, let it close the session.
Upvotes: 6