/** * removing parents and children * * @param parentId record id * @param childId record id */ private void removePath(Long parentId, Long childId) { EntityManager em = mc.getTransactionEntityManager(); // -- building branch to remove from below hierarchy >> using parent to use only this parent // path if more than one exists List<Long> pathList = em.createQuery( "SELECT rp.recordPK.path FROM RecordPath rp WHERE rp.recordPK.child = :child") .setParameter("child", parentId) .getResultList(); pathList.add(parentId); // -- retrieving hierarchies to complete with new branch >> finding all children of reference List<RecordPathPK> pkList = em.createQuery("SELECT rp.recordPK FROM RecordPath rp WHERE rp.recordPK.path = :path") .setParameter("path", childId) .getResultList(); pkList.add(new RecordPathPK(parentId, childId, parentId)); // -- applying path branch to childrens for (RecordPathPK pk : pkList) { for (Long path : pathList) { pk.setPath(path); em.remove(em.getReference(RecordPath.class, pk)); } } }
/** * Logic removing the record as well as the links. Multiple trials are preserved in comments just * for reminder on current reference implementation. * * @param <T> POJOs must extend DefaultRecord * @param recordList list of records to remove */ private <T extends Record> void removeTransaction(List<T> recordList) { // String recordType = records.get(0).getClass().getName(); // -- extracting IDs for batch processing ArrayList<Long> idList = new ArrayList<>(); for (Record record : recordList) { idList.add(record.getId()); // -- POSTGRES won't perform correctly with multiple delete query // mc.getEntityManager().createNamedQuery("RecordLink.deleteByRecordId").setParameter("record", record.getId()).executeUpdate(); // mc.getEntityManager().createNamedQuery("RecordWrapper.deleteByRecordId").setParameter("record", record.getId()).executeUpdate(); // record.setId(null); // ------------------------------------------------------------------ } // -- DELETE query less efficient than JPA remove (= batch) by x3 // mc.getEntityManager().createNamedQuery("RecordLink.deleteByRecordIdList").setParameter("list", idList).executeUpdate(); // mc.getEntityManager().createNamedQuery("RecordWrapper.deleteByRecordIdList").setParameter("list", idList).executeUpdate(); // ---------------------------------------------------------------------- EntityManager em = mc.getTransactionEntityManager(); // -- removing links // -- two queries to fetch links is more efficient than a single with OR by x10 // -- CursoredStream is effective in memory management and helps to get better performances than // EAGER fetch CursoredStream pkList1 = (CursoredStream) em.createNamedQuery("RecordLink.findByReferenceIdList") .setParameter("list", idList) .setHint("eclipselink.cursor", true) .getSingleResult(); CursoredStream pkList2 = (CursoredStream) em.createNamedQuery("RecordLink.findByLinkIdList") .setParameter("list", idList) .setHint("eclipselink.cursor", true) .getSingleResult(); // -- using reference to avoid complete loading of obsolete objects while (!pkList1.atEnd()) { for (Object pkO : pkList1.next(100)) { RecordLinkPK pk = (RecordLinkPK) pkO; em.remove(em.getReference(RecordLink.class, pk)); auditor.logRemoveLink(pk.getReference(), pk.getLink()); } } pkList1.close(); while (!pkList2.atEnd()) { for (Object pkO : pkList2.next(100)) { RecordLinkPK pk = (RecordLinkPK) pkO; em.remove(em.getReference(RecordLink.class, pk)); // no log here as duplicated } } pkList2.close(); // -- removing paths List<RecordPathPK> childList = em.createNamedQuery("RecordPath.findChildFromIdList") .setParameter("list", idList) .getResultList(); for (RecordPathPK path : childList) { removePath(path.getParent(), path.getChild()); auditor.logRemovePath(path.getParent(), path.getChild()); } List<RecordPathPK> parentList = em.createNamedQuery("RecordPath.findParentFromIdList") .setParameter("list", idList) .getResultList(); for (RecordPathPK path : parentList) { removePath(path.getParent(), path.getChild()); auditor.logRemovePath(path.getParent(), path.getChild()); } // -- removing indexes List<RecordIndexPK> indexList = em.createNamedQuery("RecordIndex.findIndexFromIdList") .setParameter("list", idList) .getResultList(); indexList .stream() .forEach( (index) -> { em.remove(em.getReference(RecordIndex.class, index)); }); // -- removing records for (Long id : idList) { RecordWrapper rw = em.getReference(RecordWrapper.class, id); em.remove(rw); auditor.logRemoveRecord(rw); } }