Spring整合Hibernate调用createCriteria提示无活跃事务的问题求助
问题:Spring管理Hibernate事务时出现无活跃事务异常
异常信息:Calling method 'createCriteria' is not valid without an active transaction (Current status: NOT_ACTIVE)
1. hibernate.cfg.xml配置
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- JDBC Database connection settings --> <property name="connection.driver_class">org.postgresql.Driver</property> <property name="connection.url">jdbc:postgresql://abc.def:1111/db_name?useSSL=false</property> <property name="connection.username">username</property> <property name="connection.password">password</property> <!-- JDBC connection pool settings ... using built-in test pool --> <property name="connection.pool_size">200</property> <!-- Echo the SQL to stdout --> <property name="show_sql">true</property> <!-- Set the current session context --> <property name="current_session_context_class">thread</property> <property name="hbm2ddl.auto">update</property> <!-- dbcp connection pool configuration --> <property name="hibernate.dbcp.initialSize">50</property> <property name="hibernate.dbcp.maxTotal">100</property> <property name="hibernate.dbcp.maxIdle">80</property> <property name="hibernate.dbcp.minIdle">50</property> <property name="hibernate.dbcp.maxWaitMillis">-1</property> <mapping class="com.mypackage.com.model.ABC" /> .... //mapping classes </session-factory> </hibernate-configuration>
2. HibernateUtils.java代码
public class HibernateUtils { private static StandardServiceRegistry registry; private static SessionFactory sessionFactory; public static SessionFactory getSessionFactory() { if (sessionFactory == null) { try { // Create registry registry = new StandardServiceRegistryBuilder().configure().build(); // Create MetadataSources MetadataSources sources = new MetadataSources(registry); // Create Metadata Metadata metadata = sources.getMetadataBuilder().build(); // Create SessionFactory sessionFactory = metadata.getSessionFactoryBuilder().build(); } catch (Exception e) { e.printStackTrace(); if (registry != null) { StandardServiceRegistryBuilder.destroy(registry); } } } return sessionFactory; } public static void shutdown() { if (registry != null) { StandardServiceRegistryBuilder.destroy(registry); } } }
3. Spring配置(注:原标注为application.properties,实际是XML配置)
<bean id="mySessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="myDataSource" /> <property name="mappingResources"> <list> <value>hibernate.cfg.xml</value> </list> </property> <property name="hibernateProperties"> <value> hibernate.dialect=org.hibernate.dialect.HSQLDialect </value> </property> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="mySessionFactory" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" />
4. 数据库调用代码
Session session = HibernateUtils.getSessionFactory().getCurrentSession(); Criteria criteria = session.createCriteria(ABC.class); //Error line ABC obj = (ABC) criteria.add(Restrictions.eq("userId", userId)).uniqueResult(); if(obj == null) return null; return obj;
5. POM依赖
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> </dependency> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.8.Final</version> </dependency>
解决方案
核心问题分析
当前代码存在两个致命冲突:
- 同时维护了自定义HibernateUtils生成的SessionFactory和Spring管理的LocalSessionFactoryBean,两者完全独立,Spring事务管理器无法管控前者生成的Session。
- Hibernate配置中的
current_session_context_class=thread会覆盖Spring的会话上下文管理逻辑,导致Spring无法将事务绑定到当前Session。
具体修复步骤
废弃HibernateUtils类,统一使用Spring注入的SessionFactory
在DAO或Service类中通过Spring注入SessionFactory:@Autowired private SessionFactory sessionFactory;获取Session时直接用注入的实例:
Session session = sessionFactory.getCurrentSession();修改hibernate.cfg.xml配置
删除<property name="current_session_context_class">thread</property>这一行,让Spring完全接管会话上下文。修正Spring配置中的数据库方言
你使用的是PostgreSQL,但配置里写的是HSQLDialect,替换为对应方言:<property name="hibernateProperties"> <value> hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect </value> </property>为数据库操作方法添加事务注解
在执行数据库查询的Service方法上标记@Transactional,触发Spring开启事务:@Transactional public ABC getABCByUserId(String userId) { Session session = sessionFactory.getCurrentSession(); Criteria criteria = session.createCriteria(ABC.class); return (ABC) criteria.add(Restrictions.eq("userId", userId)).uniqueResult(); }对齐Spring与Hibernate版本兼容性
当前用了Spring的hibernate3包,但Hibernate entitymanager版本可能不匹配。如果使用Spring 5.x及以上,建议改用Hibernate 5.x对应的Spring集成类:org.springframework.orm.hibernate5.LocalSessionFactoryBeanorg.springframework.orm.hibernate5.HibernateTransactionManager
内容的提问来源于stack exchange,提问作者Bubu Bhat
相关产品推荐
相关产品推荐

