我的应用程序崩溃并出现以下错误:
org.hibernate.HibernateException: Flush during cascade is dangerous
除非休眠代表我这样做,否则我不会冲洗。
规格:
这是我的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());
}
我为什么会收到上述错误以及如何解决?
答案 0 :(得分:1)
实体管理器不是线程安全的。在容器管理的事务中使用EntityManager很好,但是在这里您要同时管理EntityManager和事务。而且,实体管理器是静态的,因此您可以有效地重用它,以便从控制器那里获得不同的请求。传入呼叫将执行更新查询,该查询将调用刷新。
我注意到,在您的initEntityManager期间,您正在用新实例交换objectManager的静态实例。那另一个线程可能正在使用的旧引用呢?
执行以下操作:
另一种解决方案应该是使Spring或您的容器(如果您使用容器管理事务)。进行服务,使用@Transaction属性对其进行注释,并使Spring / Container在其中注入EntutyManager,或者仅使用spring-data存储库。
答案 1 :(得分:0)
flush
的Hibernate实现调用EntityTransaction
操作,在您的情况下,它可能是JdbcResourceLocalTransactionCoordinatorImpl
上的commit
。
在SessionImpl
内部,这是引发HibernateException
的原因。
private void doFlush() {
checkTransactionNeeded();
checkTransactionSynchStatus();
try {
if ( persistenceContext.getCascadeLevel() > 0 ) {
throw new HibernateException( "Flush during cascade is dangerous" );
}
...
也许,我说也许,其他一些线程抓住了Session
对象,并在您的实体上进行操作。