com.github.molcikas.photon.query.PhotonAggregateSave Maven / Gradle / Ivy
package com.github.molcikas.photon.query;
import com.github.molcikas.photon.PhotonEntityState;
import com.github.molcikas.photon.blueprints.*;
import com.github.molcikas.photon.blueprints.entity.EntityBlueprint;
import com.github.molcikas.photon.blueprints.entity.FieldBlueprint;
import com.github.molcikas.photon.blueprints.entity.FlattenedCollectionBlueprint;
import com.github.molcikas.photon.blueprints.table.TableBlueprint;
import com.github.molcikas.photon.blueprints.table.TableBlueprintAndKey;
import com.github.molcikas.photon.blueprints.table.TableValue;
import com.github.molcikas.photon.converters.Convert;
import com.github.molcikas.photon.converters.Converter;
import com.github.molcikas.photon.exceptions.PhotonOptimisticConcurrencyException;
import com.github.molcikas.photon.options.PhotonOptions;
import com.github.molcikas.photon.sqlbuilders.UpdateSqlBuilderService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.sql.Connection;
import java.util.*;
import java.util.stream.Collectors;
public class PhotonAggregateSave
{
private final AggregateBlueprint aggregateBlueprint;
private final Connection connection;
private final PhotonEntityState photonEntityState;
private final PhotonOptions photonOptions;
public PhotonAggregateSave(
AggregateBlueprint aggregateBlueprint,
Connection connection,
PhotonEntityState photonEntityState,
PhotonOptions photonOptions)
{
this.aggregateBlueprint = aggregateBlueprint;
this.connection = connection;
this.photonEntityState = photonEntityState;
this.photonOptions = photonOptions;
}
public void save(Object aggregateInstance, Collection fieldPathsToExclude)
{
PopulatedEntity aggregateRootEntity = new PopulatedEntity(aggregateBlueprint.getAggregateRootEntityBlueprint(), aggregateInstance);
saveEntitiesRecursive(aggregateBlueprint.getAggregateRootEntityBlueprint(), Collections.singletonList(aggregateRootEntity), null, null, false, fieldPathsToExclude, "");
}
public void saveAll(Collection> aggregateInstances, Collection fieldPathsToExclude)
{
List aggregateRootEntities = aggregateInstances
.stream()
.map(instance -> new PopulatedEntity(aggregateBlueprint.getAggregateRootEntityBlueprint(), instance))
.collect(Collectors.toList());
saveEntitiesRecursive(aggregateBlueprint.getAggregateRootEntityBlueprint(), aggregateRootEntities, null, null, false, fieldPathsToExclude, "");
}
public void insert(Object aggregateInstance)
{
PopulatedEntity aggregateRootEntity = new PopulatedEntity(aggregateBlueprint.getAggregateRootEntityBlueprint(), aggregateInstance);
saveEntitiesRecursive(aggregateBlueprint.getAggregateRootEntityBlueprint(), Collections.singletonList(aggregateRootEntity), null, null, true, null, "");
}
public void insertAll(Collection> aggregateInstances)
{
List aggregateRootEntities = aggregateInstances
.stream()
.map(instance -> new PopulatedEntity(aggregateBlueprint.getAggregateRootEntityBlueprint(), instance))
.collect(Collectors.toList());
saveEntitiesRecursive(aggregateBlueprint.getAggregateRootEntityBlueprint(), aggregateRootEntities, null, null, true, null, "");
}
private void saveEntitiesRecursive(
EntityBlueprint entityBlueprint,
List populatedEntities,
PopulatedEntity parentPopulatedEntity,
FieldBlueprint parentFieldBlueprint,
boolean isInsert,
Collection fieldPathsToExclude,
String fieldPath)
{
if(populatedEntities == null)
{
populatedEntities = Collections.emptyList();
}
if(fieldPathsToExclude == null)
{
fieldPathsToExclude = Collections.emptyList();
}
if(fieldPathsToExclude.contains(fieldPath))
{
return;
}
if(!isInsert)
{
Orphans.findAndDelete(entityBlueprint, populatedEntities, parentPopulatedEntity,
parentFieldBlueprint, photonEntityState, connection, photonOptions);
Orphans.findAndDeleteJoined(entityBlueprint, populatedEntities, connection, photonOptions);
}
if(populatedEntities.isEmpty())
{
return;
}
Map> updatedPopulatedEntities;
if(isInsert)
{
updatedPopulatedEntities = entityBlueprint
.getTableBlueprintsForInsertOrUpdate()
.stream()
.collect(Collectors.toMap(k -> k, v -> Collections.emptyList()));
}
else
{
updatedPopulatedEntities = updatePopulatedEntities(populatedEntities, parentPopulatedEntity, entityBlueprint);
}
Map> populatedEntitiesToInsert = new LinkedHashMap<>();
for(TableBlueprint tableBlueprint : entityBlueprint.getTableBlueprintsForInsertOrUpdate())
{
List entitiesToInsert = populatedEntities
.stream()
.filter(p -> tableBlueprint.isApplicableForEntityClass(p.getEntityInstance().getClass()))
.filter(p -> !updatedPopulatedEntities.get(tableBlueprint).contains(p))
.collect(Collectors.toList());
populatedEntitiesToInsert.put(tableBlueprint, entitiesToInsert);
}
List populatedEntitiesToInsertList = populatedEntitiesToInsert
.values()
.stream()
.flatMap(Collection::stream)
.distinct()
.collect(Collectors.toList());
if(!isInsert && entityBlueprint.getVersionField() != null)
{
if(!populatedEntitiesToInsertList.isEmpty())
{
throw new PhotonOptimisticConcurrencyException();
}
for(PopulatedEntity populatedEntity : populatedEntities)
{
populatedEntity.incrementVersionNumber();
}
}
insertPopulatedEntities(populatedEntitiesToInsert, parentPopulatedEntity, parentFieldBlueprint, entityBlueprint);
setForeignKeyToParentForPopulatedEntities(populatedEntities, entityBlueprint.getFieldsWithChildEntities());
insertAndDeleteFlattenedCollectionFields(populatedEntities, entityBlueprint.getFlattenedCollectionFields());
for(PopulatedEntity populatedEntity : populatedEntities)
{
for (FieldBlueprint fieldBlueprint : entityBlueprint.getFieldsWithChildEntities())
{
String childFieldPath = fieldPath + (StringUtils.isBlank(fieldPath) ? "" : ".") + fieldBlueprint.getFieldName();
List fieldPopulatedEntities = populatedEntity.getChildPopulatedEntitiesForField(fieldBlueprint);
saveEntitiesRecursive(
fieldBlueprint.getChildEntityBlueprint(),
fieldPopulatedEntities,
populatedEntity,
fieldBlueprint,
populatedEntitiesToInsertList.contains(populatedEntity),
fieldPathsToExclude,
childFieldPath
);
}
}
}
private Map> updatePopulatedEntities(
List populatedEntities,
PopulatedEntity parentPopulatedEntity,
EntityBlueprint entityBlueprint)
{
if(populatedEntities == null || populatedEntities.isEmpty())
{
return Collections.emptyMap();
}
Map> updatedOrUpdateToDateEntities = new LinkedHashMap<>();
for(TableBlueprint tableBlueprint : entityBlueprint.getTableBlueprintsForInsertOrUpdate())
{
final List updatedPopulatedEntitiesForTable = new ArrayList<>(populatedEntities.size());
for (PopulatedEntity> populatedEntity : populatedEntities)
{
if(!tableBlueprint.isApplicableForEntityClass(populatedEntity.getEntityInstance().getClass()))
{
continue;
}
Map trackedValues =
photonEntityState.getTrackedValues(tableBlueprint, populatedEntity.getPrimaryKey());
GetParameterValuesResult valuesForUpdateResult =
populatedEntity.getParameterValuesForUpdate(tableBlueprint, parentPopulatedEntity, trackedValues);
if(valuesForUpdateResult.isSkipped())
{
continue;
}
if(!valuesForUpdateResult.isChanged())
{
updatedPopulatedEntitiesForTable.add(populatedEntity);
continue;
}
String updateSql = tableBlueprint.getUpdateSql(valuesForUpdateResult.getValues().keySet(), photonOptions);
try(PhotonPreparedStatement updateStatement = new PhotonPreparedStatement(updateSql, false, connection, photonOptions))
{
updateStatement.setNextParameters(new ArrayList<>(valuesForUpdateResult.getValues().values()));
int rowsUpdated = updateStatement.executeUpdate();
if(rowsUpdated > 0)
{
updatedPopulatedEntitiesForTable.add(populatedEntity);
}
if(!trackedValues.isEmpty())
{
photonEntityState.updateTrackedValues(
new TableBlueprintAndKey(tableBlueprint, populatedEntity.getPrimaryKey()),
valuesForUpdateResult.getValues());
}
}
}
updatedOrUpdateToDateEntities.put(tableBlueprint, updatedPopulatedEntitiesForTable);
}
return updatedOrUpdateToDateEntities;
}
private void insertPopulatedEntities(
Map> populatedEntities,
PopulatedEntity parentPopulatedEntity,
FieldBlueprint parentFieldBlueprint,
EntityBlueprint entityBlueprint)
{
if(populatedEntities == null || populatedEntities.isEmpty())
{
return;
}
for(TableBlueprint tableBlueprint : entityBlueprint.getTableBlueprintsForInsertOrUpdate())
{
for (PopulatedEntity populatedEntity : populatedEntities.get(tableBlueprint))
{
if (!tableBlueprint.isApplicableForEntityClass(populatedEntity.getEntityInstance().getClass()))
{
continue;
}
String insertSql = tableBlueprint.getInsertSql();
boolean populateGeneratedKeys = tableBlueprint.getPrimaryKeyColumn().isAutoIncrementColumn();
boolean shouldInsertUsingPrimaryKeySql = tableBlueprint
.shouldInsertUsingPrimaryKeySql(populatedEntity, tableBlueprint);
if (shouldInsertUsingPrimaryKeySql)
{
insertSql = tableBlueprint.getInsertWithPrimaryKeySql();
populateGeneratedKeys = false;
}
try (PhotonPreparedStatement insertStatement = new PhotonPreparedStatement(
insertSql,
populateGeneratedKeys,
connection,
photonOptions))
{
List values = populatedEntity
.getParameterValuesForInsert(tableBlueprint, parentPopulatedEntity,
shouldInsertUsingPrimaryKeySql);
insertStatement.setNextParameters(values);
insertStatement.executeInsert();
if (populateGeneratedKeys)
{
Long generatedKey = insertStatement.getGeneratedKeys().get(0);
populatedEntity.setPrimaryKeyValue(generatedKey);
}
updateTrackedValuesAndAddTrackedChild(
populatedEntity,
tableBlueprint,
parentPopulatedEntity,
parentFieldBlueprint
);
}
}
}
}
private void updateTrackedValuesAndAddTrackedChild(
PopulatedEntity> populatedEntity,
TableBlueprint tableBlueprint,
PopulatedEntity> parentPopulatedEntity,
FieldBlueprint parentFieldBlueprint)
{
photonEntityState.updateTrackedValues(
tableBlueprint,
populatedEntity.getPrimaryKey(),
populatedEntity.getParameterValuesForUpdate(tableBlueprint, parentPopulatedEntity, null).getValues());
if(parentPopulatedEntity != null)
{
photonEntityState.addTrackedChild(
parentFieldBlueprint,
parentPopulatedEntity.getPrimaryKey(),
populatedEntity.getEntityBlueprint(),
populatedEntity.getPrimaryKey());
}
}
private void setForeignKeyToParentForPopulatedEntities(List populatedEntities, List fieldsWithChildEntities)
{
for(PopulatedEntity populatedEntity : populatedEntities)
{
for (FieldBlueprint fieldBlueprint : fieldsWithChildEntities)
{
List fieldPopulatedEntities = populatedEntity.getChildPopulatedEntitiesForField(fieldBlueprint);
for (PopulatedEntity fieldPopulatedEntity : fieldPopulatedEntities)
{
fieldPopulatedEntity.setForeignKeyToParentValue(populatedEntity.getPrimaryKeyValue());
}
}
}
}
private void insertAndDeleteFlattenedCollectionFields(List populatedEntities, List flattenedCollectionFields)
{
if(populatedEntities == null || populatedEntities.isEmpty())
{
return;
}
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy