【问题标题】:Spring data JPA : Transaction for every record is not commitedSpring data JPA:未提交每条记录的事务
【发布时间】:2017-06-17 19:16:49
【问题描述】:

我需要通过以下操作在循环中提交记录:

  • 删除旧状态的记录(父+子)
  • 创建新记录,插入父+子 下面的 deleteOldAndsaveNew() 方法在循环中调用,我希望每次都提交里面的操作。

PFB代码sn-p:

调用方法: //服务层

public int updateOldDocumentsFromList(List<DocumentChildDTO> childDocuments) {
            
            int nbDocsUpdated = 0;
            for (DocumentChildDTO docChildDTO : childDocuments) {

            if (docChildDTO .getDocument() != null) {
                DocumentDTO documentDTO = docChildDTO .getDocument();
                Document document =            documentMapper.documentDTOToDocument(documentDTO);
                Document latestDoc = getLatestChildDocument(document);
                

                DocumentStatus statusObsolete = docStatusService.findByName(DocumentStatusType.Obsolete.toString());
                DocumentStatus statusValidated = docStatusService.findByName(DocumentStatusType.Validated.toString());
                boolean isDBDocObsolete = isDBDocObsolete(statusObsolete, latestDoc);
                boolean createDoc = false;
                nbDocsUpdated = documentDAO.deleteObsoleteAndSaveValidatedDoc(docChildDTO, document, latestDoc, statusValidated, isDBDocObsolete,
                        nbDocsUpdated, createDoc);
            }
        }
        LOG.info("End updating olddocouments (nb docs updated: " + nbDocsUpdated + ")");
        return nbDocsUpdated;
    }

//道层

   @Transactional(propagation = Propagation.REQUIRES_NEW) 
 public int deleteObsoleteAndSaveValidatedDoc(DocumentChildDTO docChildDTO, Document document, Document latestDoc,
            DocumentStatus statusValidated, boolean isDBDocObsolete, int nbDocsUpdated, boolean createDoc) {
                DocumentStatus statusObsolete = getOldDocStatus();
                
                if ((latestDoc == null) || isDBDocObsolete(statusObsolete, latestDoc)) {
                    createDoc = true;
                }
                if (isDBDocObsolete(statusObsolete, latestDoc)) {
                    documentDAO.delete(latestDoc);
                }
                DocumentDTO documentDTO;
                if (createDoc) {
                    setters for new document
        
                    // Save the new doc
                    documentDTO = docService.save(document);
                    if (documentDTO == null) {
                        LOG.error("Error");
                    } else {
                        nbDocsUpdated++;
                    }
                    
                
        docChildDTO.setDocument(documentDTO);
                        if (save(docChildDTO) == null) {
                            LOG.error("Error");
                        }
                    }
                return nbDocsUpdated;
            }
    
    Delete document method
    
        @PersistenceContext
        private EntityManager entityManager;
        public void delete(Document obsoleteDocument)  {
                  this.entityManager.remove(obsoleteDocument);
                  this.entityManager.flush();
            }
    
        @Transactional
            public void saveDocument(Document document) {
                LOG.debug("Request to save Document : {}", document);
                this.entityManager.persist(document);
                this.entityManager.flush();
               
            }
        
        @Transactional
            public void save(DocumentChild documentChild ) {
                LOG.debug("Request to save documentChild : {}", documentChild );
              documentChildDao.saveAndFlush(documentChild);
               
            }

我已经使用实体管理器和 Spring 数据方法来查看哪一个有效,我可以看到生成了删除语句和 2 个插入语句(父和子),并且 id 也增加了,但它没有在 db 中反映/提交.

这行@Transactional(propagation = Propagation.REQUIRES_NEW) 是否不能保证每次访问deleteOldAndsaveNew() 方法时都提交其中的操作?

编辑:我已删除 (propagation = Propagation.REQUIRES_NEW) 并尝试仅在每次都需要提交的操作上使用事务。

请提出建议。

谢谢。

【问题讨论】:

  • 这里有人,如果我不够清楚,请告诉我?谢谢
  • 尝试从 DAO 方法中删除 @Transactional.. 只需在服务层使用它.. 其中定义了 deleteOldAndsaveNew 方法
  • 感谢 Maciej...从 DAO 方法中删除事务没有帮助。请问还有什么建议吗?
  • 我尝试在服务类级别上删除 @Transactional 并将其仅放在 deleteOldAndsaveNew 上,但没有成功..
  • 另外,在每次操作后调用 flush 并不是一个好主意。删除那些 .. em 将在事务结束时刷新..

标签: jpa transactions spring-data-jpa


【解决方案1】:

谢谢,我能解决这个问题。通过在单独的类中使用以下代码并从类级别中删除 Transactional。

调用方法:

public int updateObsoleteDocumentsFromList(List<DocumentChildDTO> childDocuments) {
         LOG.info("Start updating Obsolete documents (nb docs to update: " + childDocuments.size()+ ")" );

         int nbDocsUpdated = 0;
        try {
            DocumentStatus statusObsolete = docStatusService.findByName(StatusType.Old.toString());
            Status statusValidated = docStatusService.findByName(StatusType.Validated.toString());
            for (DocumentChildDTO docChildDTO : childDocuments) {
                if (docChildDTO .getDocument() != null) {
                    DocumentDTO documentDTO = docChildDTO .getDocument();
                    Document document = documentMapper.documentDTOToDocument(documentDTO);
                    nbDocsUpdated = documentDAO.deleteObsoleteAndSaveValidatedDoc(docChildDTO, document, statusValidated,  
                            nbDocsUpdated, statusObsolete);
                }
            }
        }

        return nbDocsUpdated;
    }

被调用的方法(在单独的类中)

@Transactional
    public Integer deleteObsoleteAndSaveValidatedDoc(DocumentChildDTO docChildDTO, Document document,
            DocumentStatus statusValidated, int nbDocsUpdated ,DocumentStatus statusObsolete) {

        Document latestDoc = getLatestChildDocument(document);
        boolean isDBDocObsolete = isDBDocObsolete(statusObsolete, latestDoc);
        boolean createDoc = false;
        DocumentDTO documentDTO;
        if ((latestDoc == null) || isDBDocObsolete) {
            createDoc = true;
        }

        if (isDBDocObsolete) {
            documentChildDao.deleteChildDocumentByDocId(latestDoc.getId());
            deleteDocumentById(latestDoc.getId());
        }
        if (createDoc) {
            document.setUpdateDate(new Date());
            document.setStatus(statusValidated);
            document.setIsObsolete(false);

            documentDTO = saveDocument(document);
            if (documentDTO == null) {
                LOG.error("Cannot create document " + document.getName());
            } else {
                nbDocsUpdated++;
            }
            docChildDTO.setDocument(documentDTO);
            if (documentChildDao.save(docChildDTO) == null) {
                LOG.error("Cannot create child document " + docChildDTO.getNameChild());
            }

        return nbDocsUpdated;
    }

谢谢。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-13
    • 1970-01-01
    • 2015-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-23
    相关资源
    最近更新 更多