【问题标题】:Hibernate 5.2.10.Final - javax.persistence.TransactionRequiredException: no transaction is in progressHibernate 5.2.10.Final - javax.persistence.TransactionRequiredException:没有正在进行的事务
【发布时间】:2017-05-09 14:03:45
【问题描述】:

从 Hibernate 4.3 迁移到 5.2 后,我收到错误 javax.persistence.TransactionRequiredException: no transaction is in progress。什么会导致此错误?为什么事务不存在?

public class HibernateUtil {
private static StandardServiceRegistry registry;
private static SessionFactory sessionFactory;
private static final Logger logger = LogManager.getLogger(HibernateUtil.class);
private static final ThreadLocal<Interceptor> threadInterceptor = new ThreadLocal<>();
private static final ThreadLocal<Session> threadSession = new ThreadLocal<>();

/**
 * Retrieves the current Session local to the thread.
 *
 * <p/>
 * If no Session is open, opens a new Session for the running thread.
 *
 * @return Session
 */
public static Session getSession() throws InfrastructureException {
    Session s = threadSession.get();
    try {
        if (s == null) {
            if (getInterceptor() != null) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Using interceptor: " + getInterceptor().getClass());
                }
                s = getSessionFactory().openSession();
            } else {
                s = getSessionFactory().openSession();
            }
            threadSession.set(s);
        }
    } catch (HibernateException ex) {
        throw new InfrastructureException(ex);
    }
    return s;
}

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;
}

private static Interceptor getInterceptor() {
    return threadInterceptor.get();
}

在数据库中存储对象的通用方法(BaseDAO)。 session.flush() 行中抛出错误。

protected static void storeObject(Object object) throws DAOException {
    try {
        Session session = Helper.getHibernateSession();
        session.saveOrUpdate(object);
        session.flush();
        session.beginTransaction().commit();
    } catch (HibernateException he) {
        rollback();
        throw new DAOException(he);
    }
}

UserDAO 类中的方法:

public void save(User user) throws DAOException {
    storeObject(user);
}

hibernate.cf.xml

<session-factory>
    <!-- SQL - Settings -->
    <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

    <property name="hibernate.connection.url">
        jdbc:mysql://localhost/test?autoReconnect=true&amp;autoReconnectForPools=true
    </property>
    <property name="hibernate.connection.username">test</property>
    <property name="hibernate.connection.password">test</property>

    <!-- connection pool -->
    <property name="hibernate.c3p0.max_size">5000</property>
    <property name="hibernate.c3p0.min_size">10</property>
    <property name="hibernate.c3p0.timeout">180</property>
    <property name="hibernate.c3p0.max_statements">0</property>
    <property name="hibernate.c3p0.idle_test_period">10</property>
    <property name="hibernate.c3p0.acquire_increment">1</property>
    <property name="hibernate.c3p0.validate">true</property>

    <!-- use the C3P0 connection pool -->
    <property name="connection.provider_class">
        org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider
    </property>

    <!-- Enable Hibernate's automatic session context management -->
    <property name="current_session_context_class">managed</property>

    <!-- Don't echo all executed SQL to stdout -->
    <property name="show_sql">false</property>
    <property name="hibernate.bytecode.use_reflection_optimizer">false</property>

    <!-- Validate database schema on startup -->
    <property name="hbm2ddl.auto">validate</property>

    <!-- Mapping -->
    <mapping class="org.test.data.database.beans.User"/>

</session-factory>

【问题讨论】:

    标签: java hibernate migration


    【解决方案1】:

    线

    session.beginTransaction().commit();
    

    开始然后立即提交(结束)事务。但是您的flush() 需要介于两者之间。试试这个:

    protected static void storeObject(Object object) throws DAOException {
      Transaction tx = null;
      try {
        Session session = Helper.getHibernateSession();
        session.saveOrUpdate(object);
        tx = session.beginTransaction();
        session.flush();
        tx.commit();
      } catch (HibernateException he) {
        if(tx != null){
          tx.rollback();
        } 
        throw new DAOException(he);
      }
    }
    

    【讨论】:

    • 我有同样的错误,但所有的操作都是这样的:Session session = HibernateUtil.getSessionFactory().openSession();尝试 { session.beginTransaction(); session.saveOrUpdate(entityObj); session.getTransaction().commit(); } catch (RuntimeException e) { session.getTransaction().rollback(); e.printStackTrace(); } 最后 { session.flush(); session.close(); }
    • 隐式使用和直接使用事务有区别吗?
    • 谢谢你,这对我帮助很大!
    猜你喜欢
    • 2016-05-11
    • 2010-12-20
    • 2012-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多