Java 如何在多线程应用程序中使用 Hibernate?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18215370/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:23:35  来源:igfitidea点击:

How to use Hibernate in a multi threaded application?

javahibernate

提问by Rahul

I am trying to use Hibernate for a multi threaded application wherein each thread retrieves an object and tries to insert it into a table. My code looks like below. I have local hibernate Session objects per thread and in each InsertData I do beginTransaction and commit.

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

The problem I am facing is that many times I get "org.hibernate.TransactionException: nested transactions not supported"

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

Since I am new to hibernate I don't know if what I am doing is correct or not? Please let me know what is the correct way to use hibernate in multi threaded app and how to avoid the above mentioned exception.

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

Thanks

谢谢

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

My hibernate config file has c3p0.min_size=10and c3p0.max_size=20

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

采纳答案by Jason C

With session-objects-per-thread, as long as you are not sharing session objects between multiple threads, you will be fine.

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

The error you are receiving is unrelated to your multithreaded usage or your session management. Your usage of session.save()as well as explicitly setting the ID is not quite right.

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

Without seeing your mapping for BlogPostits hard to tell, but if you have told Hibernate to use the idfield as the primary key, and you are using the native generator for primary keys, the all you need to do is this:

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

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

Hibernate will fill in the ID for you, persist()will cause the insert to happen within the bounds of the transaction (save()does not care about transactions). If your flush mode is not set to manual then you don't need to call flush()as Transaction.commit()will handle that for you.

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

Note that with persist(), the BlogPost's ID is not guaranteed to be set until the session is flushed, which is fine for your usage here.

请注意,使用persist(),在刷新会话之前不能保证设置 BlogPost 的 ID,这对于您在此处的使用来说很好。

To handle errors gracefully:

优雅地处理错误:

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
}

By the way, I suggesting making BlogPost.setId()private, or package visible. It is most likely an implementation error if another class sets the ID explicitly (again assuming native generator, and id as primary key).

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