Spring data JPA:未提交每条记录的事务
Posted
技术标签:
【中文标题】Spring data JPA:未提交每条记录的事务【英文标题】:Spring data JPA : Transaction for every record is not commited 【发布时间】: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 将在事务结束时刷新.. 【参考方案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;
谢谢。
【讨论】:
以上是关于Spring data JPA:未提交每条记录的事务的主要内容,如果未能解决你的问题,请参考以下文章
Spring-data-jpa + Hibernate 未创建预期表
Spring Data JPA - 防止一对一关系的双重表单提交
spring spring data jpa save操作事务
带有spring boot JPA Postgresql的data.sql未加载