我尝试使用一个EntityManager打开事务两次:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("HelloWorldPU");
EntityManager em = emf.createEntityManager();
Message message0 = new Message();
message0.setText("Hi!!");
em.getTransaction().begin();
em.persist(message0);
em.getTransaction().commit();
em.close();
Message message1 = new Message();
message1.setText("Bye!!");
System.out.println("i'm here");
em.getTransaction().begin();
em.persist(message1);
em.getTransaction().commit();
em.close();
并获得例外:
我在这里
线程中的异常" main" java.lang.IllegalStateException:org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl@31e4bb20已关闭
我的猜测是:无法从关闭的EntityManager获取另一个事务。但是JPA Spec说:
EntityManager.close
方法关闭实体管理器以释放其持久性上下文和其他资源。调用close
后,除EntityManager
和getTransaction
外,应用程序不得在isOpen
实例上调用任何其他方法,否则将引发IllegalStateException
。如果在事务处于活动状态时调用close
方法,则持久性上下文将保持受管状态,直到事务完成。
有人可以解释我错在哪里吗?没有调用getTransaction
的可能性意味着我可以使用此交易和ivoke交易的方法吗?
谢谢。
更新
感谢您的回答,这些对我来说最有帮助:
1:
您可以使用EntityManager,直到您调用close,是。没有 "重新打开"方法。创建一个EntityManager是一个廉价的操作 - 尼尔 斯托克顿13分钟前
2:
您可以调用getTransaction来检查事务是否处于活动状态。宇 也可以关闭带有活动tx的EntityManager(作为文档 状态)并在收盘后提交)。因此你可以打电话 getTransaction。 - M. Deinum 9分钟前
答案 0 :(得分:1)
这里的现实是你的第一次close()调用是没有必要的。你实际想要实现的是拥有两个孤立的交易 - 完全有效。有两种基本方法可以做到这一点。
1)提交事务,在同一个实体管理器实例上启动一个新事务。我滥用缩进来显示实体经理的生存时间的示例:
EntityManager em = emf.createEntityManager();
Message message0 = new Message();
message0.setText("Hi!!");
em.getTransaction().begin();
em.persist(message0);
em.getTransaction().commit();
// no close here
Message message1 = new Message();
message1.setText("Bye!!");
System.out.println("i'm here");
em.getTransaction().begin();
em.persist(message1);
em.getTransaction().commit();
em.close();
2)关闭实体经理并创建一个新的(正如评论中所说的那样便宜)
EntityManager em = emf.createEntityManager();
Message message0 = new Message();
message0.setText("Hi!!");
em.getTransaction().begin();
em.persist(message0);
em.getTransaction().commit();
em.close();
// create new EntityManager
em = emf.createEntityManager();
Message message1 = new Message();
message1.setText("Bye!!");
System.out.println("i'm here");
em.getTransaction().begin();
em.persist(message1);
em.getTransaction().commit();
em.close();
您选择哪个选项取决于应用程序功能的进一步设计;例如,选项1)对缓存更友好,并且可能在事务之间维护第一级缓存。如果事务与数据源中的数据更改之间存在延迟,则存在缓存中缓存实体变为陈旧的风险,即事务之间对em.clear()
的调用可以解决。
当我实现事务批处理逻辑时,我倾向于选择2),例如:文件导入逻辑,它泵入大量的记录,这些记录将以较小的块进行处理和提交。在任何其他情况下,选项1)通常都可以正常工作。
答案 1 :(得分:-1)
尝试对您的代码进行以下更改:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("HelloWorldPU");
EntityManager em = emf.createEntityManager();
Message message0 = new Message();
em.getTransaction().begin();
message0.setText("Hi!!");
em.persist(message0);
em.getTransaction().commit();
em.close();
EntityManagerFactory emf1 = Persistence.createEntityManagerFactory("HelloWorldPU");
EntityManager em1 = emf.createEntityManager();
Message message1 = new Message();
em1.getTransaction().begin();
message1.setText("Bye!!");
System.out.println("i'm here");
em1.persist(message1);
em1.getTransaction().commit();
em1.close();
尝试并恢复!EM关闭后,您应该创建/打开一个新的。