我正在尝试将Hibernate用于多线程应用程序,其中每个线程都检索一个对象并将其插入表中。我的代码如下所示。我每个线程都有本地hibernate会话对象,在每个InsertData中,我都执行beginTransaction和commit。
我面临的问题是很多次我收到“ org.hibernate.TransactionException:不支持嵌套事务”
由于我是hibernate的新手,所以我不知道自己在做的事是否正确?请让我知道在多线程应用中使用hibernate的正确方法是什么,以及如何避免上述异常。
谢谢
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();
}
}
我的hibernate配置文件有c3p0.min_size=10
和c3p0.max_size=20
使用每个线程会话对象,只要您不在多个线程之间共享会话对象,就可以了。
您收到的错误与多线程用法或会话管理无关。您session.save()
对ID的使用以及明确设置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为主键),则很可能是实现错误。
问题内容: 是否有一种实际的方法可以在PHP中实现多线程模型,无论是真正的还是仅对其进行仿真。一段时间以前,建议您可以强制操作系统加载PHP可执行文件的另一个实例并处理其他同时进行的进程。 这样做的问题是,当PHP代码完成执行PHP实例后,它仍保留在内存中,因为无法从PHP中杀死它。因此,如果您正在模拟多个线程,则可以想象会发生什么。因此,我仍在寻找一种可以在PHP中有效完成或模拟多线程的方法。有
问题内容: 在多线程应用程序中如何使用Hibernate(例如,每个客户端连接在服务器上启动它自己的线程)。 EntityManager应该仅由EntityManagerFactory创建一次,例如: 还是我必须为每个线程以及关闭EM的每个事务重新创建实体? 我的CRUD方法如下所示: 我要不要每次都跑?还是因为每个人都使用自己的缓存创建自己的EntityManager实例而使我陷入麻烦了? 问题
问题内容: 自两年以来,我一直在使用java(Servlets,JSPs)进行Web应用程序开发。在那两年中,我从不需要在任何项目中使用(明确地- 众所周知,servlet容器使用线程为不同的请求提供相同的servlet)。 但是,每当我参加Web开发人员职位(java)的面试时,就会有几个与java中的线程相关的问题。我知道Java线程的基础知识,因此回答问题不是问题。但是有时我会感到困惑,是否
我正在使用作为我的一个库中的。我不确定我是否在多线程环境中正确地使用它,因为我的库在多线程环境中会在非常大的负载下使用,所以它必须非常快。 下面是我的DataClient类: 这就是我要打电话获取数据的方式: 现在我的问题是--我不确定我是否正确地将与一起使用。这里是否需要以及? 我的主要目标是在多线程环境中高效地使用。因为我的库将在非常大的负荷下使用,所以它必须非常快。在重载下,我看到了大量的T
问题内容: 我将python解释器嵌入到多线程C应用程序中,对于应该使用哪些API来确保线程安全,我有些困惑。 从我收集到的信息来看,嵌入python时,在调用任何其他Python C API调用之前,由嵌入器负责GIL锁定。这是通过以下功能完成的: 但是,仅此一项似乎还不够。我仍然遇到随机崩溃,因为它似乎并未为Python API提供互斥。 阅读更多文档后,我还添加了: 在致电之后,但这就是令人
问题内容: 我正在使用SQL Server 2008。 我有一个表A,它在一秒钟内接受许多插入/更新。插入后,更新我想获取受影响的行数。 在执行查询时,同一查询可以由应用程序再次调用。因此,如果当前执行是 在INSERT之后但在IF块之前,该 怎么办。 您认为出于这个原因可能会给出错误的结果吗? 还是在它的上下文中总是安全的? 问题答案: 是的-它很安全。它始终引用当前查询中的上一个操作 但 如果