首页 > 解决方案 > 将持久化实体保留在事务之外

问题描述

我有一个场景,我试图将复杂数据导入我的数据库(具有子对象和列表对象的对象,一些用于更新,而另一些用于新插入)。现在,我正在使用的一般流程如下:

void importData(List dataToImport){
     Object persistedObject1 = getObjectFromDB(); // data that will be attached to various objects in my import
     HashMap map1 = preFillMap1();  // Fills a map with persisted objects from database to be attached to data
     HashMap map2 = emptyMap(); // start with an empty map here
     try{
         for(Object data : dataToImport){
                Object dbSavedData = importDataImpl(persistedObject1, map2, map3, data)
                map2.put(dbSavedData.getChild().getRecordID(), dbSavedData.getChild())
         }
     }catch(Exception e){
           logger.error("Error in transaction", e);
     }
}

@org.springframework.transaction.annotation.Transactional
void importDataImpl(Object persistedObj, HashMap map1, HashMap map2, Object dataToImport){
      // simplified import process
      dataToImport.setForeignKeyObject1(persistedObj);
      dataToImport.setForeignKeyObject2(map1.get(dataToImport.obj2ID));
      if(map2.contains(dataToImport.getChild().getRecordID()){
            dataToImport.setForeignKeyObject3(map2.get(dataToImport.obj3ID));
      }else{
            dataToImport.setForeignKeyObject3(repo.findByID(dataToImport.getChild().getRecordID());
      }
      jpaRepo.save(dataToImport);           
}

我在上面遇到的问题是,一旦我在 importDataImpl 中遇到错误,我会在以后的调用中遇到以下错误:

detached entity passed to persist: com.project.ChildObject; nested exception is org.hibernate.PersistentObjectException: 
detached entity passed to persist: com.project.ChildObject org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist:com.project.ChildObject

到目前为止,我能够解决它的唯一方法是在出错时重置地图并重试 importDataImpl 调用。它在第二次运行时没有问题,但保留地图的目的是减少所需的数据库调用次数。我已经看到了一些关于进行 entityManager.contains(obj) 检查的建议,但据我所知,这并不可靠,也不是最优雅的解决方案,因为我仍然需要重置地图。在这一点上,捕捉错误并在那里处理它似乎更干净。

标签: javaspringhibernatespring-bootjpa

解决方案


也许你可以试试 entity.merge()。

merge() 会将陈旧状态推送到数据库,并覆盖任何干预更新


推荐阅读