Как разрешить отсутствие сеанса для текущего потока

Я пытался сделать общий способ реализации DAO, и я следил за статьей

Ниже приведен мой класс genericDaoImpl

@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
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;
        }

    }

Это мой 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 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>  

Я не могу найти причину

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)

Ответ 1

Вы попытались удалить следующее свойство:

<prop key="hibernate.transaction.auto_close_session">true</prop>

Я считаю, что Hibernate закроет сессию слишком рано и приведет к вашей ошибке. Поскольку вы используете Spring TransactionManager, пусть он закрывает сеанс.

Ответ 2

вам нужно добавить следующий код в xml файл конфигурации hibernate

<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>

Ответ 3

Вам нужно удалить аннотацию @Transactional из метода репозитория, использовать только аннотацию @Transactional для метода уровня обслуживания.

   @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);

 }

Ответ 4

Удалить аннотацию @Transactional от функции и использовать ее на уровне класса.

Ответ 5

<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactoryConf" />
</bean>

Ответ 6

Это происходит, когда вы пытаетесь сохранить изменения в бизнес-объекте после завершения транзакции.

Думаю, вам стоит взглянуть на Spring Data JPA? Он предлагает гораздо больше, чем общий DAO.