没有活动事务,get无效 - hibernate 5

ped*_*dja 7 java hibernate-5.x

即使我手动启动了交易,我仍然会收到此错误.

Session session = HibernateUtil.getSessionFactory().getCurrentSession();
transaction = session.getTransaction();
if(!transaction.isActive())
{
    transaction = session.beginTransaction();
}

accessToken = session.get(OAuthAccessToken.class, token);
Run Code Online (Sandbox Code Playgroud)

hibernate.cfg.xml

<property name="hibernate.connection.autoReconnect">true</property>

    <!-- Use the C3P0 connection pool. -->
    <property name="hibernate.c3p0.min_size">5</property>
    <property name="hibernate.c3p0.max_size">20</property>
    <property name="hibernate.c3p0.timeout">300</property>
    <property name="hibernate.c3p0.max_statements">50</property>
    <property name="hibernate.c3p0.idle_test_period">3000</property>

    <!-- Disable second-level cache. -->
    <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
    <property name="cache.use_query_cache">false</property>
    <property name="cache.use_minimal_puts">false</property>
    <property name="max_fetch_depth">3</property>

    <!-- Bind the getCurrentSession() method to the thread. -->
    <property name="current_session_context_class">thread</property>

    <property name="hibernate.jdbc.batch_size">30</property>
Run Code Online (Sandbox Code Playgroud)

HibernateUtils

public class HibernateUtil
{
private static final SessionFactory sessionFactory;

static
{
    try
    {
        // Create the SessionFactory from hibernate.cfg.xml
        Configuration config = new Configuration().configure();
        config.setProperty("hibernate.show_sql", String.valueOf(ConfigManager.getInstance().getBoolean(Consts.CONFIG_DB_SHOW_SQL, false)));
        config.setProperty("hibernate.format_sql", String.valueOf(ConfigManager.getInstance().getBoolean(Consts.CONFIG_DB_FORMAT_SQL, false)));

        config.setProperty("hibernate.dialect", ConfigManager.getInstance().getString(Consts.CONFIG_DB_DIALECT, "org.hibernate.dialect.MySQLDialect"));
        config.setProperty("hibernate.connection.driver_class", ConfigManager.getInstance().getString(Consts.CONFIG_DB_DRIVER_CLASS, "com.mysql.jdbc.Driver"));
        config.setProperty("hibernate.connection.url", ConfigManager.getInstance().getString(Consts.CONFIG_DB_URL, "jdbc:mysql://localhost/photometo"));
        config.setProperty("hibernate.connection.useUnicode", "true");
        config.setProperty("hibernate.connection.characterEncoding", "UTF-8");
        config.setProperty("hibernate.connection.username", ConfigManager.getInstance().getString(Consts.CONFIG_DB_USERNAME, "root"));
        config.setProperty("hibernate.connection.password", ConfigManager.getInstance().getString(Consts.CONFIG_DB_PASSWORD, ""));
        config.setProperty("hibernate.hbm2ddl.auto", ConfigManager.getInstance().getString(Consts.CONFIG_DB_HBMDDL_AUTO, "update"));
        sessionFactory = config.buildSessionFactory();
    }
    catch (Throwable ex)
    {
        throw new ExceptionInInitializerError(ex);
    }
}

public static SessionFactory getSessionFactory()
{
    return sessionFactory;
}

}
Run Code Online (Sandbox Code Playgroud)

我注意到这会在一段时间后开始发生.如果我重新启动tomcat或重新部署应用程序,问题就会消失

Gat*_*sko 2

您从未开始过交易,也无法获得其他人的交易。这就是为什么你在调用它时会收到错误:

    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
    transaction = session.getTransaction(); // Here is the error! You can't get an active transaction, becasue there isn't even started 
    if(!transaction.isActive()) // transaction.isActive() is usually for closing a transction in the end
    {
        transaction = session.beginTransaction(); // You are starting the transaction!
    }

accessToken = session.get(OAuthAccessToken.class, token);
Run Code Online (Sandbox Code Playgroud)

您无法获得活动交易,因为甚至还没有开始。将代码更改为:

 // Non-managed environment idiom with getCurrentSession()
try {
    factory.getCurrentSession().beginTransaction();

    // do some work
    ...

    factory.getCurrentSession().getTransaction().commit();
}
catch (RuntimeException e) {
    factory.getCurrentSession().getTransaction().rollback();
    throw e; // or display error message
}
Run Code Online (Sandbox Code Playgroud)

在非托管环境中启动事务的正确原因来自Hibernate 文档

// Non-managed environment idiom with getCurrentSession()
try {
    factory.getCurrentSession().beginTransaction();

    // do some work
    ...

    factory.getCurrentSession().getTransaction().commit();
}
catch (RuntimeException e) {
    factory.getCurrentSession().getTransaction().rollback();
    throw e; // or display error message
}

// Non-managed environment idiom with getCurrentSession() try {
    factory.getCurrentSession().beginTransaction();

    // do some work
    ...

    factory.getCurrentSession().getTransaction().commit(); } catch (RuntimeException e) {
    factory.getCurrentSession().getTransaction().rollback();
    throw e; // or display error message }
Run Code Online (Sandbox Code Playgroud)

根据getTransaction()的文档,您当前的会话未启动事务。

getTransaction()
      Get the Transaction instance associated with this session.
Run Code Online (Sandbox Code Playgroud)

这就是为什么要启动事务11.2 数据库事务划分

数据库或系统、事务边界始终是必要的。在数据库事务之外不能发生与数据库的通信(这似乎让许多习惯自动提交模式的开发人员感到困惑)。始终使用清晰的事务边界,即使对于只读操作也是如此。

长事务对数据库不利,因为会在数据库、会话和事务范围中生成大量锁

为了减少数据库中的锁争用,数据库事务必须尽可能短。长数据库事务将阻止您的应用程序扩展到高度并发的负载。不建议您在用户思考时间内保持数据库事务打开,直到工作单元完成。