com.kenshoo.pl.entity.internal.DbCommandsOutputGenerator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of persistence-layer Show documentation
Show all versions of persistence-layer Show documentation
A Java persistence layer based on JOOQ for high performance and business flow support.
package com.kenshoo.pl.entity.internal;
import com.google.common.base.Stopwatch;
import com.kenshoo.jooq.DataTable;
import com.kenshoo.pl.data.*;
import com.kenshoo.pl.entity.*;
import com.kenshoo.pl.entity.spi.OutputGenerator;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.jooq.ForeignKey;
import org.jooq.Record;
import org.jooq.TableField;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.stream.Stream;
import static com.kenshoo.pl.entity.ChangeOperation.CREATE;
import static com.kenshoo.pl.entity.HierarchyKeyPopulator.autoInc;
import static com.kenshoo.pl.entity.HierarchyKeyPopulator.fromContext;
import static org.jooq.lambda.Seq.seq;
import static org.jooq.lambda.function.Functions.not;
public class DbCommandsOutputGenerator> implements OutputGenerator {
private final E entityType;
private final CommandsExecutor commandsExecutor;
public DbCommandsOutputGenerator(E entityType, PLContext plContext) {
this.commandsExecutor = CommandsExecutor.of(plContext.dslContext());
this.entityType = entityType;
}
@Override
public void generate(Collection extends EntityChange> entityChanges, ChangeOperation operator, ChangeContext changeContext) {
Stopwatch stopwatch = Stopwatch.createStarted();
if (operator == ChangeOperation.DELETE) {
generateForDelete(changeContext, entityChanges);
} else {
final ChangesContainer primaryTableCommands =
generateForCreateOrUpdate(entityChanges,
this::isOfPrimaryTable,
operator,
changeContext);
entityType.getPrimaryIdentityField().ifPresent(identityField -> {
if (operator == CREATE) {
populateGeneratedIdsToContext(identityField,
entityChanges,
changeContext,
primaryTableCommands);
//noinspection unchecked
new HierarchyKeyPopulator.Builder()
.with(changeContext.getHierarchy())
.whereParentFieldsAre(autoInc())
.gettingValues(fromContext(changeContext)).build()
.populateKeysToChildren((Collection extends ChangeEntityCommand>)entityChanges);
}
}
);
generateForCreateOrUpdate(entityChanges,
not(this::isOfPrimaryTable),
operator,
changeContext);
}
changeContext.getStats().addUpdateTime(stopwatch.elapsed(TimeUnit.MILLISECONDS));
}
private void populateGeneratedIdsToContext(final EntityField identityField,
Collection extends EntityChange> entityChanges,
ChangeContext changeContext,
ChangesContainer changesContainer) {
final TableField identityTableField = getFirstTableField(identityField);
seq(entityChanges)
.map(change -> ImmutablePair.of(change, changesContainer.getInsert(entityType.getPrimaryTable(), change)))
.filter(pair -> pair.getRight().isPresent())
.forEach(pair -> {
final CreateRecordCommand cmd = pair.getRight().get();
Object generatedValue = cmd.get(identityTableField);
changeContext.addEntity(pair.getLeft(), new EntityWithGeneratedId(identityField, generatedValue));
});
}
private TableField getFirstTableField(final EntityField entityField) {
return entityField.getDbAdapter().getTableFields()
.findFirst()
.orElseThrow(() -> new IllegalStateException("No table fields found for an entity field"));
}
private boolean isOfPrimaryTable(FieldChange f) {
return f.getField().getDbAdapter().getTable() == entityType.getPrimaryTable();
}
private void translateChange(EntityChange entityChange, FieldChange change, ChangesContainer changesContainer, ChangeOperation changeOperation, ChangeContext changeContext) {
EntityField entityField = change.getField();
if (!entityField.isVirtual()) {
translateChange(entityChange, change, entityField, changesContainer, changeOperation, changeContext);
}
}
private void translateChange(final EntityChange entityChange, final FieldChange change, final EntityField entityField, final ChangesContainer changesContainer, final ChangeOperation changeOperation, final ChangeContext changeContext) {
final DataTable fieldTable = entityField.getDbAdapter().getTable();
final DataTable primaryTable = entityType.getPrimaryTable();
AbstractRecordCommand recordCommand;
if (fieldTable == primaryTable) {
if (changeOperation == CREATE) {
recordCommand = changesContainer.getInsert(primaryTable, entityChange, () -> newCreateRecord(entityChange));
} else {
recordCommand = changesContainer.getUpdate(primaryTable, entityChange, () -> new UpdateRecordCommand(primaryTable, getDatabaseId(entityChange)));
}
} else {
recordCommand = changesContainer.getInsertOnDuplicateUpdate(fieldTable, entityChange, () -> {
CreateRecordCommand createRecordCommand = new CreateRecordCommand(fieldTable);
populate(foreignKeyValues(entityChange, changeOperation, changeContext, fieldTable), createRecordCommand);
return createRecordCommand;
});
}
populateFieldChange(change, recordCommand);
}
private CreateRecordCommand newCreateRecord(EntityChange entityChange) {
CreateRecordCommand cmd = new CreateRecordCommand(entityType.getPrimaryTable());
populateParentKeys(entityChange, cmd);
return cmd;
}
private void populateFieldChange(FieldChange, T> change, AbstractRecordCommand recordCommand) {
T value = change.getValue();
Iterator> tableFields = change.getField().getDbAdapter().getTableFields().iterator();
Iterator