/** * deleting records from the database * * @param <T> POJOs must extend DefaultRecord * @param records list of records to remove from the database */ public <T extends Record> void remove(List<T> records) { if (!records.isEmpty()) { // -- removing records by max batch of PARAMETER_PAGING which is the max number of paramaters // supported by some databases (ex PostgreSQL) // -- single transaction for all deletes to preserve integrity and faster processing (batch // SQL). mc.transaction( () -> { int start = 0; int end = Math.min(records.size(), PARAMETER_PAGING); while (start < records.size()) { removeTransaction(records.subList(start, end)); start = end; end = Math.min(records.size(), end + PARAMETER_PAGING); } }); // -- if transaction is successfull unvalidating IDs records .stream() .forEach( (record) -> { record.setId(-1L); }); } }
/** * saving and cloning records * * @param <T> POJOs must extend DefaultRecord * @param recordClass class of the records to clone * @param records records to clone * @return list of cloned and saved records */ public <T extends Record> List<T> clone(Class<T> recordClass, T... records) { RecordWrapper cloneWrapper = new RecordWrapper(); List<T> list = new ArrayList<>(); mc.transaction( () -> { // saving records save(records); // cloning for (T record : records) { RecordWrapper wrapper = mc.getTransactionEntityManager().find(RecordWrapper.class, record.getId()); cloneWrapper.setRecordType(wrapper.getRecordType()); cloneWrapper.setTenant(wrapper.getTenant()); if (wrapper.getData() != null) { cloneWrapper.setData(wrapper.getData()); } //// if (wrapper.getDocument() != null) { //// cloneWrapper.setDocument(wrapper.getDocument()); //// } // performing database operations mc.getTransactionEntityManager().persist(cloneWrapper); T recordClone = mc.getRecord(recordClass, wrapper); indexRecord(true, recordClone); auditor.logCreateRecord(cloneWrapper); list.add(recordClone); } }); return list; }
/** * Saving records to the database. JPA handles bath writing, so parameter paging can be ignored * (vs remove). * * @param <T> POJOs must extend DefaultRecord * @param list list of records to save in the database */ public <T extends Record> void save(List<T> list) { if (list != null) { mc.transaction( () -> { list.stream() .filter((record) -> (record != null)) .forEach( (record) -> { Long recordId = record.getId(); if (recordId == null) { // persisting new record RecordWrapper wrapper = createRecordWrapper(record); indexRecord(true, record); auditor.logCreateRecord(wrapper); } else { // using reference as only SET is necesssary RecordWrapper wrapper = mc.getTransactionEntityManager() .getReference( RecordWrapper.class, recordId); // getReference creating two queries including // RecordType wrapper.setData(mc.toWrapper(record)); //// if (record.isDocumentChanged()) { //// wrapper.setDocument(record.getDocument()); //// } indexRecord(false, record); auditor.logUpdateRecord(wrapper, false); // //record.isDocumentChanged()); } }); }); } }
/** * Spawn transaction to group multiple writing operations. Otherwise a transaction is * encapsulating each operation. * * @param runnable for Lambda */ public void transaction(Runnable runnable) { mc.transaction(runnable); }