【问题标题】:Hibernate opening session twice and transaction required休眠两次打开会话并需要事务
【发布时间】:2015-04-14 15:42:08
【问题描述】:

首先,如果本网站有与我的问题相关的内容,我想道歉。我什么也找不到。 我正在开发一个 spring+hibernate 应用程序,该应用程序链接到用 AngularJS 编写的前端。 例如,当我从前端调用特定操作时:

@MessageMapping("/markVoicemailAsRead/{uniqueId}")
public void markRead(@DestinationVariable int uniqueId) {
    Session session = sessionFactory.openSession();
    Transaction tx = null;
    try {
        tx = session.beginTransaction();
        voiceMailDao.setVoiceMailRead(uniqueId);
        tx.commit();
    } catch (HibernateException e) {
        if (tx != null)
            tx.rollback();
        e.printStackTrace();
    } finally {
        session.close();
    }
}

一切都很好,它可以在我的 postgres 数据库中正常工作。我发现奇怪的是,在setVoiceMailRead(uniqueId) 中我必须打开另一个会话,而且我还需要一个事务对象。这是setVoiceMailRead(uniqueId)的实现:

    public void setVoiceMailRead(int id) {
    Session session = sessionFactory.openSession();
    Transaction transaction = null;
    Query query = session.createQuery("update VoiceMail set read = :read"
            + " where uniqueId = :id");
    try {
        transaction = session.beginTransaction();
        query.setParameter("read", true);
        query.setParameter("id", id);
        query.executeUpdate();
        transaction.commit();
    } catch (HibernateException e) {
        if (transaction != null)
            transaction.rollback();
        e.printStackTrace();
    } finally {
        session.close();
    }
}

如果我在 markRead 操作中删除会话 ant 事务,我会在控制台“无活动事务”中收到错误,所以我就这样离开了。我认为我的hibernate.xml 文件和<property> 标签有问题:

<property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL9Dialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.current_session_context_class">thread</prop> </props> </property>

提前感谢您的回复!

【问题讨论】:

    标签: java hibernate postgresql session transactions


    【解决方案1】:

    在第一个类中无需打开会话对象并提交事务,只需对方法进行分类

    setVoiceMailRead(uniqueId) 在你的 markRead(-) 方法中。

    【讨论】:

    • 谢谢!正如我所说,如果我这样做,我会收到错误:没有活动交易:(
    【解决方案2】:

    虽然 JPA 不需要事务来进行读取操作(回退到自动提交),但所有 write operations require a transaction

    必须调用persist、merge、remove 和refresh 方法 在事务上下文中,当实体管理器具有 使用事务范围的持久性上下文。如果没有 交易上下文 抛出 javax.persistence.TransactionRequiredException。

    不需要调用 find 和 getReference 方法 在事务上下文中。如果实体经理与 事务范围的持久性上下文正在使用中,结果 实体将被分离;如果实体管理器具有扩展 使用持久性上下文,它们将被管理。

    setVoiceMailRead你需要打电话:

    Session session = sessionFactory.getCurrentSession();
    

    获得你在 root 方法中打开的同一个 Hibernate Session。而且只能在 root 方法中关闭。

    【讨论】:

    • 非常感谢您的回答!我会试试的:)
    • 我做到了,不幸的是出现了这个错误:createQuery is not valid without active transaction at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:352)
    • thread 会话上下文应该允许您重用应该注册根事务的相同会话。您需要在 Hibernate 代码中对其进行调试。
    猜你喜欢
    • 2014-07-26
    • 2011-06-13
    • 2017-06-19
    • 2017-09-04
    • 1970-01-01
    • 2015-10-07
    • 1970-01-01
    • 2013-08-09
    相关资源
    最近更新 更多