示例#1
0
 /**
  * parsing record to extract indexed fields
  *
  * @param isNew record has never been parsed
  * @param record record to parse
  */
 private void indexRecord(boolean isNew, Record record) {
   for (Field field : mc.getIndexingField(record.getClass())) {
     try {
       // indexes can be shared by providing common key, or default key using field path is used
       String key = field.getAnnotation(FieldIndexing.class).value();
       String name = field.getName();
       if (key.length() == 0) {
         key = record.getClass().getName() + "." + name;
       }
       // reading field value to add to index list
       boolean status = field.isAccessible();
       field.setAccessible(true);
       Object fieldValue = field.get(record);
       field.setAccessible(status);
       // database access
       EntityManager em = mc.getTransactionEntityManager();
       RecordIndexPK pk = new RecordIndexPK(key, record.getId(), name);
       // forcing indexe deletion to preserve record batch save (npreveting select for each save)
       // Note : make sure the ModelController provides an entity manager with
       // setShouldPerformDeletesFirst(true)
       if (!isNew) {
         em.remove(em.getReference(RecordIndex.class, pk));
       }
       // mapping the index to the database
       Comparable converted = pm.getConverted(fieldValue);
       if (converted != null) {
         RecordIndex ri = new RecordIndex(pk);
         switch (pm.getType(field.getType())) {
           case DATE:
             ri.setDate((Date) converted);
             break;
           case STRING:
             ri.setValue((String) converted);
             break;
           case NUMERIC:
             ri.setNumeric((BigDecimal) converted);
             break;
         }
         // saving
         em.persist(ri);
       }
     } catch (IllegalArgumentException | IllegalAccessException ex) {
       // convet to runtime exception
       throw new RuntimeException(ex);
     }
   }
 }
示例#2
0
  /**
   * 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);
    }
  }