如何在多线程应用程序中使用休眠?

2022-09-04 03:43:20

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

我面临的问题是,很多时候我得到“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


答案 1

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

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

没有看到你的映射很难分辨,但是如果你已经告诉Hibernate使用字段作为主键,并且你正在使用本机生成器作为主键,那么你需要做的就是:BlogPostid

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

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

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

要正常处理错误::

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
}

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


答案 2

推荐