@Override
  public void commit() {
    if (isDisable) {
      return;
    }
    InvocationContext context = InvocationContext.get();

    // Here we have to prepare Output data for this transaction.
    ChangesTracker tracker = context.getDbChanges();

    // Save only ids for all added instances(including children to delete it
    // while reverting)
    List<Instance> added = tracker.getAdded();

    // Get only changes for updated instances
    Set<Instance> updated = new HashSet<Instance>();
    List<Instance> changes = tracker.getUpdated();
    changes = filterChild(changes);

    changes.forEach(
        u ->
            updated.add(
                getChanges(
                    u,
                    i -> {
                      Instance old = tracker.getOld(i.getId());
                      if (old != null) {
                        return old;
                      }
                      return context.getDatabase().load(i.getId(), false);
                    },
                    false)));

    // Save complete instances for all deleted instances
    Set<Instance> deleted = new HashSet<Instance>();
    List<Instance> deletedObjs = filterChild(tracker.getDeleted());
    deletedObjs.forEach(d -> deleted.add(tracker.getOld(d.getId())));

    TxOutputDataFull full = new TxOutputDataFull();
    full.setAdded(added);
    full.setUpdated(updated);
    full.setDeleted(deleted);
    full.setAddedModelHierachy(addedModelHierarchies);
    full.setRemovedModelHierachy(deletedModelHierarchies);
    full.setAddedClassHierachy(addedClassHierarchies);
    full.setRemovedClassHierachy(deletedClassHierarchies);
    full.setAddedQueryPlans(insertedQueryPlans);
    full.setUpdatedQueryPlans(updateQueryPlans);
    full.setDeletedQueryPlans(deletedQueryPlans);
    full.setCreatedShares(
        sharesCreated.stream().map(s -> s.getInstance()).collect(Collectors.toSet()));
    full.setDeletedShares(sharesDeleted);

    byte[] output = null;
    byte[] input = null;
    try {
      output = SerializationUtil.kryoSerialize(full);
      MutableLong initialId = new MutableLong(1L);
      inputs.forEach(i -> allocateDuplicateId(i, initialId));
      input = SerializationUtil.kryoSerializeInstances(inputs);
    } catch (Exception e) {
      // TODO
    }

    // Preparing createdPrefixBitset
    BitSet created = new BitSet();
    added.forEach(i -> created.set(i._type()));

    // Save it in database
    TxData data = new TxData();
    data.setInputs(input);
    data.setAllocatedIds(allocatedIds);
    data.setOutput(output);
    data.setType(isDelete ? TxData.DELETE : TxData.UPSERT);
    data.setCreatedPrefixes(created);
    data.setFullOutput(full);
    data.setTxDone(new Timestamp(new Date().getTime()));
    data.setServerId(context.getServerId());
    data.setTxDoneBy(context.getUserId());
    this.txdata = data;
  }