пытается использовать HibernateTransactionManager, но транзакционные службы выдают HibernateException

Я пытаюсь преобразовать проект Spring 4 для использования HibernateTransactionManager для управления транзакциями, но транзакционные службы выдают это исключение:

org.hibernate.HibernateException: createSQLQuery недействителен без активной транзакции

Я искал в Google, и у 80 разных людей есть 80 разных способов сделать это. Я пробовал их все, и либо они не работают, либо требуют использования EntityManager вместо Hibernate Sessions. Поскольку я преобразовываю существующий код, использующий сеансы Hibernate, все было бы намного проще, если бы я мог заставить их работать. Как избавиться от этого исключения?

  • Весенняя версия: 4.2.5.РЕЛИЗ
  • Спящая версия: 5.1.0.Final
  • Версия Хикари: 2.7.6
  • Версия JDK: 1.8.0_161

Конфигурация источника данных:

@Configuration
public class DataSourceConfig {
    @Bean
    public DataSource dataSource() {
        // return a Hikari connection pool as the data source
        try {
            HikariDataSource bean = new HikariDataSource();
            // set connection pool and JDBC properties
            return bean;
        } catch (Exception e) {
            throw new RuntimeException("could create data source", e);
        }
    }
}

Конфигурация фабрики сеансов:

@Configuration
public class SessionFactoryConfig {
    @Autowired
    private DataSource dataSource;

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        // create a session factory
        try {
            LocalSessionFactoryBean bean = new LocalSessionFactoryBean();
            // set Hibernate properties
            bean.setDataSource(dataSource);
            bean.setPackagesToScan(packagesToScan);
            bean.setHibernateProperties(properties);
            bean.afterPropertiesSet(); // tried without this line as well
            return bean;
        } catch (Exception e) {
            throw new RuntimeException("could not create session factory", e);
        }
    }
}

Конфигурация транзакции:

@Configuration
@EnableTransactionManagement
@ComponentScan("com.mydomain.*")
public class TransactionConfig {
    @Autowired
    private SessionFactory sessionFactory;

    @Bean
    public PlatformTransactionManager transactionManager() {
        HibernateTransactionManager bean = new HibernateTransactionManager(sessionFactory);
//      bean.setHibernateManagedSession(true); // similar exception when set
        bean.afterPropertiesSet(); // tried without this line as well
        return bean;
    }
}

Услуга:

@Service
@Transactional // tried using only the @Transactional on the method
public class TestTransactionService {
    @Autowired
    private SessionFactory sessionFactory;

    @Transactional // tried using only the @Transactional on the class
    public String get(String key) {
        Session session = sessionFactory.getCurrentSession();
        // the below line throws the exception!
        SQLQuery q = session.createSQLQuery("SELECT value FROM test_transaction WHERE key = :key");
        q.setParameter("key", key);
        q.addScalar("value", StringType.INSTANCE);
        String out = (String)q.uniqueResult();
        return out;
    }
}

Любые идеи? Я надеюсь на это, потому что я выхожу.


person Alvin Thompson    schedule 02.03.2018    source источник
comment
Стоит проверить ваш импорт; убедитесь, что вы используете аннотацию Spring @Transaction (org.springframework.transaction.annotation.Transactional), а НЕ javax.transactional. Легко пропустить.   -  person GrumpyWelshGit    schedule 03.03.2018
comment
@GrumpyWelshGit да, я. import org.springframework.transaction.annotation.Transactional;   -  person Alvin Thompson    schedule 03.03.2018
comment
У вас есть hibernate.cfg.xml и hibernate.properties? если да, проверьте конфигурации или удалите их.   -  person Y.Kaan Yılmaz    schedule 03.03.2018
comment
@kaanyılmaz: нет   -  person Alvin Thompson    schedule 03.03.2018
comment
Не могли бы вы добавить эту строку Transaction ts = session.beginTransaction(); и используйте его после объявления сеанса. И используйте @Transactional на уровне метода, если вы действительно не хотите сделать каждый метод вашего класса транзакционным.   -  person Y.Kaan Yılmaz    schedule 03.03.2018
comment
@kaanyılmaz, как я уже упоминал в комментариях, пробовал и то, и другое.   -  person Alvin Thompson    schedule 03.03.2018
comment
Я только что дал совет по поводу аннотации @Transactional, вы пытались добавить Transaction ts = session.beginTransaction(); после создания сеанса?   -  person Y.Kaan Yılmaz    schedule 03.03.2018
comment
Да, это работает — изначально код был написан именно так. Весь смысл этого заключается в том, чтобы избежать ручного управления транзакцией.   -  person Alvin Thompson    schedule 03.03.2018


Ответы (1)


В наших настройках был спрятан этот невинно выглядящий, он был там с момента первоначальной проверки git нашего проекта, поэтому я не могу выяснить, кто его вставил (им повезло):

hibernate.current_session_context_class = поток

Поскольку никто не знал, для чего предназначена эта настройка, с тех пор никто не осмеливался ее трогать. Это нарушает транзакции, управляемые Spring, и не имеет никакого отношения к этому.

Пусть это будет уроком, мальчики и девочки: если вы пытаетесь заставить что-то работать, НЕ возитесь с настройками, когда вы не знаете, что это такое. Это вернется, чтобы укусить вас за задницу, иногда спустя годы. А потом я найду тебя и заберу.

person Alvin Thompson    schedule 03.03.2018