@Transactional не создает транзакцию hibernate

Рейтинг: 2Ответов: 3Опубликовано: 09.02.2015

В файле бинов спринга имеются такие строки:

<context:annotation-config />   
<context:component-scan base-package="com.pack"/>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager"
              class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="sessionFactory"/>
     <property name="dataSource" ref="dataSource"></property>
</bean>

Боб, в котором объявлена фабрика сессий:

@Bean(name = "sessionFactory")
    public LocalSessionFactoryBean localSessionFactoryBean() {
        LocalSessionFactoryBean factory = new LocalSessionFactoryBean();
        factory.setDataSource(dataSourceConfiguration.dataSource());

        Properties props = new Properties();
        props.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
        props.put("hibernate.hbm2ddl.auto", "update");
//        props.put("hibernate.current_session_context_class", "thread");
        factory.setHibernateProperties(props);
        factory.setMappingResources("com/pack/Item.hbm.xml");

        return factory;
    }

Бины dataSource и sessionFactory отдельно работают нормально, думаю, проблема не в них. Имеется DAO:

@Repository(value = "itemDaoHibernateImpl")
public class ItemDaoHibernateImpl implements ItemDao {

    @Resource(name = "sessionFactory")
    private SessionFactory factory;

    public void setFactory(SessionFactory factory) {
        this.factory = factory;
    }

    public Session session() {
        return factory.getCurrentSession();
    }

    @Override
    public void create(Item item) {
        session().save(item);
    }

Сессии в нем не открываю, т.к. хочу заставить спринг делать это. Имеется класс Service c таким вот методом:

@Override
@Transactional
public void create(Item item) {
    dao.create(item);
}

При запуске этого метода падает вот такой эксепшн:

org.hibernate.HibernateException: save is not valid without active transaction

Делал как сказано тут, ещё пару гайдов прочитал левых, но в них сессия открывается руками в каждом методе в ДАО, а мне это не нужно. Как сделать, чтоб работало? Где ошибка?

Ответы

▲ 2Принят

Порылся в карманах, нашел свой конфиг:

 <bean id="sessionFactory" class="org.sprigframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="configurationClass">
      <value>org.hibernate.cfg.AnnotationConfiguration</value>
    </property>
    <property name="hibernateProperties">
      <props>
        <prop key="hibernate.show_sql">true</prop>
        <prop key="hibernate.dialect">${jdbc.dialect}</prop>
        <prop key="hibernate.connection.charset">UTF-8</prop>
      </props>
    </property>

    <property name="annotatedClasses">
        <list>
            <value>...</value>
        </list>
    </property>
  </bean>

Как видите, hibernate.current_session_context_class не задан (совсем как у вас то есть) и все работает. Почему? Spring сам заинжектит свой SpringSessionContext для поддержки транзакций в scope-е своих сессий и запросов.

▲ 2

Попробуйте добавить аннотацию @Transactional к классу дао.

@Repository(value = "itemDaoHibernateImpl")
@Transactional
public class ItemDaoHibernateImpl implements ItemDao {
    ....
}
▲ 1

Проблему решил. Удалил параметр из хиба hibernate.current_session_context_class, который имел значение thread. Это работает, но не понимаю, как тогда хиб будет определять, создавать новую сессию или гетить существующую методом currentSession().