尝试使用 HibernateTransactionManager,但事务服务抛出 HibernateException
trying to use HibernateTransactionManager, but transactional services throw HibernateException
我正在尝试将 Spring 4 项目转换为使用 HibernateTransactionManager 来管理事务,但事务服务抛出此异常:
org.hibernate.HibernateException: createSQLQuery is not valid without
active transaction
我在 google 上搜索过,80 个不同的人有 80 种不同的方法。我已经尝试了所有这些方法,要么它们不起作用,要么它们需要使用 EntityManager 而不是 Hibernate Sessions。由于我正在转换使用 Hibernate 会话的现有代码,如果我能让它们工作,事情会容易得多。我如何摆脱这个异常?
- Spring版本:4.2.5.RELEASE
- 休眠版本: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;
}
}
有什么想法吗?我希望如此,因为我出去了。
埋在我们的设置中的是这个 innocent-looking 一个,自从我们项目的初始 git 签入以来就在那里,所以我无法找出是谁把它放进去的(他们很幸运):
hibernate.current_session_context_class = thread
因为没人知道这个设置是干什么用的,所以以后就没人敢碰了。这破坏了 Spring 托管交易,并且没有业务在那里。
让我们作为一个教训,男孩和女孩们:如果你想让一些东西发挥作用,不要只是 fiddle 在你不知道它们是什么的情况下进行设置。它会回来咬你的屁股——有时是几年后。然后我会来找你并得到你。
我正在尝试将 Spring 4 项目转换为使用 HibernateTransactionManager 来管理事务,但事务服务抛出此异常:
org.hibernate.HibernateException: createSQLQuery is not valid without active transaction
我在 google 上搜索过,80 个不同的人有 80 种不同的方法。我已经尝试了所有这些方法,要么它们不起作用,要么它们需要使用 EntityManager 而不是 Hibernate Sessions。由于我正在转换使用 Hibernate 会话的现有代码,如果我能让它们工作,事情会容易得多。我如何摆脱这个异常?
- Spring版本:4.2.5.RELEASE
- 休眠版本: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;
}
}
有什么想法吗?我希望如此,因为我出去了。
埋在我们的设置中的是这个 innocent-looking 一个,自从我们项目的初始 git 签入以来就在那里,所以我无法找出是谁把它放进去的(他们很幸运):
hibernate.current_session_context_class = thread
因为没人知道这个设置是干什么用的,所以以后就没人敢碰了。这破坏了 Spring 托管交易,并且没有业务在那里。
让我们作为一个教训,男孩和女孩们:如果你想让一些东西发挥作用,不要只是 fiddle 在你不知道它们是什么的情况下进行设置。它会回来咬你的屁股——有时是几年后。然后我会来找你并得到你。