java - hibernate/jpa 抱怨“级联时刷新”
问题描述
我的应用程序因以下错误而崩溃:
org.hibernate.HibernateException: Flush during cascade is dangerous
除非 hibernate 代表我这样做,否则我不会脸红。
眼镜:
- Tomcat上的webapp
- hibernate/jpa 用于持久性(应用程序托管实体管理器)
这是我的 util 类管理实体管理器的代码:
private static EntityManagerFactory emFactory = Persistence.createEntityManagerFactory("returnit");
private static EntityManager entityManager;
public static EntityManager getEntityManager(){
return entityManager;
}
public static EntityManager initEntityManager(){
if (emFactory == null) {
emFactory = Persistence.createEntityManagerFactory( "returnit" );
}
entityManager = emFactory.createEntityManager();
return entityManager;
}
这是触发错误的方法:
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response post(@HeaderParam(HttpHeaders.AUTHORIZATION) String authHeader, MasterCrossDock mcd) {
EntityManager em = Utils.initEntityManager();
em.getTransaction().begin();
MasterCrossDockDAO.save(mcd);
em.getTransaction().commit();
em.close();
return Response.ok(mcd.getId()).build();
}
public static void save(MasterCrossDock new_mcd) {
List<Receptacle> receptacles = new_mcd.getReceptacles();
List<Long> ids = new ArrayList<Long>();
for (Receptacle r: receptacles) {
ids.add(r.getId());
}
new_mcd.getReceptacles().clear();
EntityManager em = Utils.getEntityManager();
new_mcd.getCountryDestination())
em.createQuery("UPDATE receptacle r"
+ " SET r.masterCrossDock.id = :mcd_id"
+ " WHERE r.id IN :ids")
.setParameter("ids", ids)
.setParameter("mcd_id", new_mcd.getId())
.executeUpdate();
new_mcd.getEreturns());
}
为什么会出现上述错误以及如何解决?
解决方案
实体管理器不是线程安全的。在容器管理的事务中使用 EntityManager 很好,但在这里您要自己管理 EntityManager 和事务。此外,实体管理器是静态的,因此您可以在可能从控制器获得的不同请求上有效地重用它。来电将执行更新查询,该查询将调用刷新。
我注意到在您的 initEntityManager 期间,您正在将 entityManager 的静态实例与新实例交换。另一个线程可能正在使用的旧引用呢?
请执行下列操作:
- 完全删除您的方法 initEntityManager
- 删除私有静态EntityManager entityManager;
- 让你方法 Utils.getEntityManager(); 离开创建一个新的EntityManager
如果您使用容器管理事务,替代解决方案应该是让 Spring 或您的容器。创建一个服务,使用 @Transaction 属性对其进行注释并让 Spring/Container 在其中注入 EntutyManager,或者只使用 spring-data 存储库。
推荐阅读
- rust - Rust 找不到 extern crate 的 extern crate
- sql - 计数案例返回错误的结果
- clojure - Clojure 中的 `def` 语句中使用的环境变量
- python-3.x - 两列之间的 Groupby 协方差
- c# - 存储库模式中的分页、排序和搜索在哪里?
- java - Spring Boot AOP 方面导致 autwired bean 返回 null
- amazon-web-services - 在 DynamoDB (aws-cli) 中按非键字段过滤
- database - 将此 Btree 索引从 Postgres 转换为 Oracle
- sql - 在 SQL Server 中增加总小时数
- html - 窗口调整大小时的动画定位