【问题标题】:How to use Hibernate in a multi threaded application?如何在多线程应用程序中使用 Hibernate?
【发布时间】:2013-08-13 17:20:24
【问题描述】:

我正在尝试将 Hibernate 用于多线程应用程序,其中每个线程检索一个对象并尝试将其插入表中。我的代码如下所示。 我每个线程都有本地休眠会话对象,并且在每个 InsertData 中我执行 beginTransaction 和 commit。

我面临的问题是我多次收到“org.hibernate.TransactionException:不支持嵌套事务”

由于我是休眠新手,我不知道我所做的是否正确?请让我知道在多线程应用程序中使用休眠的正确方法是什么以及如何避免上述异常。

谢谢

public class Worker extends Thread {
private Session session = null;

Worker() {
    SessionFactory sf = HibernateUtil.getSessionFactory(); // Singleton
    session = sf.openSession();
    session.setFlushMode(FlushMode.ALWAYS);
}

public void run() {
    // Some loop which will run thousand of times 
    for (....)
    {
        InsertData(b);
    }
    session.close();
}

// BlogPost Table has (pk = id AutoGenerated), dateTime, blogdescription etc. 
private void InsertData(BlogPost b) {
    session.beginTransaction();
    Long id = (Long) session.save(b);
    b.setId(id);
    session.getTransaction().commit();
}
}

我的休眠配置文件有c3p0.min_size=10c3p0.max_size=20

【问题讨论】:

  • 应该是b.setId()
  • 是的,刚刚更正了。尝试创建我的实际代码的最小示例时发生错字。

标签: java hibernate


【解决方案1】:

使用每线程会话对象,只要您不在多个线程之间共享会话对象,就可以了。

您收到的错误与您的多线程使用或会话管理无关。您对session.save() 的使用以及显式设置ID 不太正确。

没有看到BlogPost 的映射很难说,但是如果您告诉 Hibernate 使用 id 字段作为主键,并且您正在使用本机生成器作为主键,那么您只需要这样做:

session.beginTransaction();
session.persist(b);
session.flush(); // only needed if flush mode is "manual"
session.getTransaction().commit();

Hibernate 会为你填写 ID,persist() 会导致插入发生在事务的范围内(save() 不关心事务)。如果您的刷新模式未设置为手动,则您无需致电flush(),因为Transaction.commit() 会为您处理。

请注意,使用persist(),BlogPost 的 ID 不能保证在会话刷新之前设置,这适合您在此处使用。

优雅地处理错误:

try {
    session.beginTransaction();
    try {
        session.persist(b);
        session.flush(); // only needed if flush mode is "manual"
        session.getTransaction().commit();
    } catch (Exception x) {
        session.getTransaction().rollback();
        // log the error
    }
} catch (Exception x) {
    // log the error
}

顺便说一句,我建议将BlogPost.setId() 设为私有,或将包设为可见。如果另一个类显式设置了 ID(再次假设原生生成器,并且 id 作为主键),则很可能是实现错误。

【讨论】:

  • 谢谢 Jason,我没有 rollback(),因为之前的异常使线程的事务处于打开状态,而随后的 beginTransation 用于抛出“TransactionException”。
猜你喜欢
  • 1970-01-01
  • 2018-04-28
  • 2010-09-09
  • 2019-05-22
  • 1970-01-01
  • 2015-03-13
  • 2010-12-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多