You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>

解决方案

核心问题分析

当前代码存在两个致命冲突:

  1. 同时维护了自定义HibernateUtils生成的SessionFactory和Spring管理的LocalSessionFactoryBean,两者完全独立,Spring事务管理器无法管控前者生成的Session。
  2. Hibernate配置中的current_session_context_class=thread会覆盖Spring的会话上下文管理逻辑,导致Spring无法将事务绑定到当前Session。

具体修复步骤

  1. 废弃HibernateUtils类,统一使用Spring注入的SessionFactory
    在DAO或Service类中通过Spring注入SessionFactory:

    @Autowired
    private SessionFactory sessionFactory;
    

    获取Session时直接用注入的实例:

    Session session = sessionFactory.getCurrentSession();
    
  2. 修改hibernate.cfg.xml配置
    删除<property name="current_session_context_class">thread</property>这一行,让Spring完全接管会话上下文。

  3. 修正Spring配置中的数据库方言
    你使用的是PostgreSQL,但配置里写的是HSQLDialect,替换为对应方言:

    <property name="hibernateProperties">
        <value>
            hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
        </value>
    </property>
    
  4. 为数据库操作方法添加事务注解
    在执行数据库查询的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();
    }
    
  5. 对齐Spring与Hibernate版本兼容性
    当前用了Spring的hibernate3包,但Hibernate entitymanager版本可能不匹配。如果使用Spring 5.x及以上,建议改用Hibernate 5.x对应的Spring集成类:

    • org.springframework.orm.hibernate5.LocalSessionFactoryBean
    • org.springframework.orm.hibernate5.HibernateTransactionManager

内容的提问来源于stack exchange,提问作者Bubu Bhat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 06:24:59