首页 文章

Spring应用程序中的多个entityManager . 持久存在重复对象问题

提问于
浏览
0

我的Spring组件从客户端获取请求,向Web服务询问某些数据并将接收到的对象保存到数据库 . 我 identify 所有对象和 save only new 个 .

The issue occurs 当客户端同时发出两个或多个相同的请求时(或者由于甚至不同的用户请求,我从Web服务接收相同的对象) .

在这里用 persistence 描述一些细节问题 . 对于每个客户端请求,我的组件在一个单独的线程中开始执行,我得到一个新的entityManager,开始一个事务,从web-service接收数据,然后我在当前事务中使用给定的entityManager识别对象并保留新的对象 .

如果在单独的事务中,我从Web服务接收相同的对象,如果它们是尚未在数据库中的新对象,则在未提交的事务中是 not able to identify them ,因此它们将保留在 all 事务中 . Then all duplicate objects will be commited and saved to database.

在这种情况下,什么是好的解决方案?即使在不同的交易中,有没有办法正确地使用 identify 新对象?或者可以应用哪些方法?

可能 Spring 提供了一些管理事务或entityManagers的方法,以便它可以帮助解决这个问题......

Note . 当然,我可以使用数据库工具来避免保存重复的对象,但在这种情况下,它不是一个非常好的解决方案 .

2 回答

  • 0

    所以我的案例中的解决方案如下:

    • 使事务非常小并分别提交每个对象 .

    • 在数据库中创建唯一约束以防止重复对象 . 这一点对我们来说不会有太多帮助,但需要第3点 .

    • 我们在try-catch块中插入的每个commit()方法 . 如果我们尝试在并行事务中提交重复对象,那么我们将收到一个异常,并且在catch块中我们可以检查数据库,选择已经存在的对象并进一步使用它 .

    这个例子:

    boolean reidentifyNeed = false;
    
    try {
    
        DofinService.getEntityManagerThreadLocal().getTransaction().begin();
    
        DofinService.getEntityManagerThreadLocal().persist(entity);
    
        try {
    
            DofinService.getEntityManagerThreadLocal().getTransaction().commit();
    
            //if commit is successfull
            entityIdInDB = (long) entity.getId();
    
            DofinService.getEntityManagerThreadLocal().clear();
    
        } catch (Exception ex) {
    
            logger.error("Error committing " + entity.getClass().getSimpleName() + " in DB. Possibly duplicate object. Will try to re-identify object. Error: " + ex.toString());
    
            reidentifyNeed = true;
    
        }
    
        if(reidentifyNeed){
            //need clear entityManager, because if duplicated object was persisted then during *select* an object flush() method will be executed and it will thrown ConstrainViolationException 
            DofinService.getEntityManagerThreadLocal().clear();
    
            CheckSimilarObject checkSimilarObject = new CheckSimilarObject();
    
            long objectId = checkSimilarObject.checkObject(dofinObject);
    
            logger.warn("Re-identifying was done. EntityId = " + objectId);
    
            entityIdInDB = objectId;
        }
    
    } catch (Exception ex) {
        logger.error("Error persisting and commiting object: " + ex.toString());
    }
    
  • 0

相关问题