use of io.micronaut.data.model.jpa.criteria.PersistentEntityRoot in project micronaut-data by micronaut-projects.
the class UpdateMethodMatcher method batchUpdate.
private UpdateCriteriaMethodMatch batchUpdate(java.util.regex.Matcher matcher, ParameterElement idParameter) {
return new UpdateCriteriaMethodMatch(matcher) {
@Override
protected <T> void applyPredicates(String querySequence, ParameterElement[] parameters, PersistentEntityRoot<T> root, PersistentEntityCriteriaUpdate<T> query, SourcePersistentEntityCriteriaBuilder cb) {
super.applyPredicates(querySequence, parameters, root, query, cb);
ParameterElement versionParameter = Arrays.stream(parameters).filter(p -> p.hasAnnotation(Version.class)).findFirst().orElse(null);
Predicate predicate;
if (versionParameter != null) {
predicate = cb.and(cb.equal(root.id(), cb.parameter(idParameter)), cb.equal(root.version(), cb.parameter(versionParameter)));
} else {
predicate = cb.equal(root.id(), cb.parameter(idParameter));
}
query.where(predicate);
}
@Override
protected <T> void applyPredicates(List<ParameterElement> parameters, PersistentEntityRoot<T> root, PersistentEntityCriteriaUpdate<T> query, SourcePersistentEntityCriteriaBuilder cb) {
ParameterElement versionParameter = parameters.stream().filter(p -> p.hasAnnotation(Version.class)).findFirst().orElse(null);
Predicate predicate;
if (versionParameter != null) {
predicate = cb.and(cb.equal(root.id(), cb.parameter(idParameter)), cb.equal(root.version(), cb.parameter(versionParameter)));
} else {
predicate = cb.equal(root.id(), cb.parameter(idParameter));
}
query.where(predicate);
}
@Override
protected <T> void addPropertiesToUpdate(MethodMatchContext matchContext, PersistentEntityRoot<T> root, PersistentEntityCriteriaUpdate<T> query, SourcePersistentEntityCriteriaBuilder cb) {
List<ParameterElement> parameters = matchContext.getParametersNotInRole();
List<ParameterElement> remainingParameters = parameters.stream().filter(p -> !p.hasAnnotation(Id.class) && !p.hasAnnotation(Version.class)).collect(Collectors.toList());
ParameterElement idParameter = parameters.stream().filter(p -> p.hasAnnotation(Id.class)).findFirst().orElse(null);
if (idParameter == null) {
throw new MatchFailedException("ID required for update method, but not specified");
}
SourcePersistentEntity entity = (SourcePersistentEntity) root.getPersistentEntity();
// Validate @IdClass for composite entity
if (entity.hasIdentity()) {
SourcePersistentProperty identity = entity.getIdentity();
String idType = TypeUtils.getTypeName(identity.getType());
String idParameterType = TypeUtils.getTypeName(idParameter.getType());
if (!idType.equals(idParameterType)) {
throw new MatchFailedException("ID type of method [" + idParameterType + "] does not match ID type of entity: " + idType);
}
} else {
throw new MatchFailedException("Cannot update by ID for entity that has no ID");
}
for (ParameterElement parameter : remainingParameters) {
String name = getParameterName(parameter);
SourcePersistentProperty prop = entity.getPropertyByName(name);
if (prop == null) {
throw new MatchFailedException("Cannot update non-existent property: " + name);
} else {
if (prop.isGenerated()) {
throw new MatchFailedException("Cannot update a generated property: " + name);
} else {
query.set(name, cb.parameter(parameter));
}
}
}
}
};
}
use of io.micronaut.data.model.jpa.criteria.PersistentEntityRoot in project micronaut-data by micronaut-projects.
the class UpdateMethodMatcher method batchUpdate2.
private UpdateCriteriaMethodMatch batchUpdate2(java.util.regex.Matcher matcher) {
return new UpdateCriteriaMethodMatch(matcher) {
@Override
protected <T> void addPropertiesToUpdate(MethodMatchContext matchContext, PersistentEntityRoot<T> root, PersistentEntityCriteriaUpdate<T> query, SourcePersistentEntityCriteriaBuilder cb) {
Set<String> queryParameters = query.getParameters().stream().map(ParameterExpression::getName).collect(Collectors.toSet());
for (ParameterElement p : matchContext.getParametersNotInRole()) {
String parameterName = getParameterName(p);
if (queryParameters.contains(parameterName)) {
continue;
}
PersistentPropertyPath path = root.getPersistentEntity().getPropertyPath(parameterName);
if (path != null) {
query.set(path.getProperty().getName(), cb.parameter(p));
} else {
throw new MatchFailedException("Cannot perform batch update for non-existent property: " + parameterName);
}
}
}
};
}
use of io.micronaut.data.model.jpa.criteria.PersistentEntityRoot in project micronaut-data by micronaut-projects.
the class UpdateMethodMatcher method entityUpdate.
private UpdateCriteriaMethodMatch entityUpdate(java.util.regex.Matcher matcher, ParameterElement entityParameter, ParameterElement entitiesParameter) {
return new UpdateCriteriaMethodMatch(matcher) {
ParameterElement entityParam = entityParameter == null ? entitiesParameter : entityParameter;
@Override
protected <T> void applyPredicates(List<ParameterElement> parameters, PersistentEntityRoot<T> root, PersistentEntityCriteriaUpdate<T> query, SourcePersistentEntityCriteriaBuilder cb) {
final SourcePersistentEntity rootEntity = (SourcePersistentEntity) root.getPersistentEntity();
Predicate predicate;
if (rootEntity.getVersion() != null) {
predicate = cb.and(cb.equal(root.id(), cb.entityPropertyParameter(entityParam)), cb.equal(root.version(), cb.entityPropertyParameter(entityParam)));
} else {
predicate = cb.equal(root.id(), cb.entityPropertyParameter(entityParam));
}
query.where(predicate);
}
@Override
protected <T> void addPropertiesToUpdate(MethodMatchContext matchContext, PersistentEntityRoot<T> root, PersistentEntityCriteriaUpdate<T> query, SourcePersistentEntityCriteriaBuilder cb) {
final SourcePersistentEntity rootEntity = matchContext.getRootEntity();
Stream.concat(rootEntity.getPersistentProperties().stream(), Stream.of(rootEntity.getVersion())).filter(p -> p != null && !((p instanceof Association) && ((Association) p).isForeignKey()) && !p.isGenerated() && p.findAnnotation(AutoPopulated.class).map(ap -> ap.getRequiredValue(AutoPopulated.UPDATEABLE, Boolean.class)).orElse(true)).forEach(p -> query.set(p.getName(), cb.entityPropertyParameter(entityParam)));
if (((AbstractPersistentEntityCriteriaUpdate<T>) query).getUpdateValues().isEmpty()) {
// Workaround for only ID entities
query.set(rootEntity.getIdentity().getName(), cb.entityPropertyParameter(entityParam));
}
}
@Override
protected boolean supportedByImplicitQueries() {
return true;
}
@Override
protected Map.Entry<ClassElement, Class<? extends DataInterceptor>> resolveReturnTypeAndInterceptor(MethodMatchContext matchContext) {
Map.Entry<ClassElement, Class<? extends DataInterceptor>> e = super.resolveReturnTypeAndInterceptor(matchContext);
ClassElement returnType = e.getKey();
if (returnType != null && !TypeUtils.isVoid(returnType) && !TypeUtils.isNumber(returnType) && !returnType.hasStereotype(MappedEntity.class) && !(TypeUtils.isReactiveOrFuture(matchContext.getReturnType()) && TypeUtils.isObjectClass(returnType))) {
throw new MatchFailedException("Cannot implement update method for specified return type: " + returnType.getName());
}
return e;
}
@Override
protected ParameterElement getEntityParameter() {
return entityParameter;
}
@Override
protected ParameterElement getEntitiesParameter() {
return entitiesParameter;
}
};
}
use of io.micronaut.data.model.jpa.criteria.PersistentEntityRoot in project micronaut-data by micronaut-projects.
the class SourcePersistentEntityCriteriaQueryImpl method getQueryResultTypeName.
@Override
public String getQueryResultTypeName() {
if (selection instanceof ISelection) {
String[] result = new String[1];
((SelectionVisitable) selection).accept(new SelectionVisitor() {
@Override
public void visit(Predicate predicate) {
}
@Override
public void visit(PersistentPropertyPath<?> persistentPropertyPath) {
result[0] = ((SourcePersistentPropertyPath) persistentPropertyPath).getProperty().getType().getName();
}
@Override
public void visit(AliasedSelection<?> aliasedSelection) {
((SelectionVisitable) aliasedSelection.getSelection()).accept(this);
}
@Override
public void visit(PersistentEntityRoot<?> entityRoot) {
result[0] = ((SourcePersistentEntity) entityRoot.getPersistentEntity()).getType().getName();
}
@Override
public void visit(AggregateExpression<?, ?> aggregateExpression) {
switch(aggregateExpression.getType()) {
case COUNT:
case COUNT_DISTINCT:
result[0] = Long.class.getName();
break;
case MAX:
case MIN:
result[0] = requireProperty(aggregateExpression.getExpression()).getProperty().getTypeName();
break;
case SUM:
case AVG:
ClassElement type = ((SourcePersistentProperty) requireProperty(aggregateExpression.getExpression()).getProperty()).getType();
if (aggregateExpression.getExpressionType() != null) {
result[0] = aggregateExpression.getExpressionType().getName();
}
if (TypeUtils.isNumber(type)) {
result[0] = Number.class.getName();
} else {
result[0] = type.getName();
}
break;
default:
return;
}
}
@Override
public void visit(CompoundSelection<?> compoundSelection) {
if (compoundSelection.getCompoundSelectionItems().size() == 1) {
// Multiple selection shouldn't result in one type
compoundSelection.getCompoundSelectionItems().forEach(s -> ((SelectionVisitable) s).accept(this));
}
}
@Override
public void visit(LiteralExpression<?> literalExpression) {
result[0] = literalExpression.getValue().getClass().getName();
}
@Override
public void visit(IdExpression<?, ?> idExpression) {
SourcePersistentEntity persistentEntity = (SourcePersistentEntity) idExpression.getRoot().getPersistentEntity();
if (persistentEntity.hasCompositeIdentity()) {
throw new IllegalStateException("IdClass is unknown!");
}
result[0] = persistentEntity.getIdentity().getType().getName();
}
});
return result[0];
}
return null;
}
use of io.micronaut.data.model.jpa.criteria.PersistentEntityRoot in project micronaut-data by micronaut-projects.
the class UpdateCriteriaMethodMatch method apply.
/**
* Apply query match.
*
* @param matchContext The match context
* @param root The root
* @param query The query
* @param cb The criteria builder
* @param <T> The entity type
*/
protected <T> void apply(MethodMatchContext matchContext, PersistentEntityRoot<T> root, PersistentEntityCriteriaUpdate<T> query, SourcePersistentEntityCriteriaBuilder cb) {
String querySequence = matcher.group(3);
if (matcher.group(2).endsWith("By")) {
applyPredicates(querySequence, matchContext.getParameters(), root, query, cb);
} else {
applyPredicates(matchContext.getParametersNotInRole(), root, query, cb);
}
if (query.getRestriction() == null) {
throw new MatchFailedException("Cannot implement batch update operation that doesn't perform a query");
}
SourcePersistentEntity entity = matchContext.getRootEntity();
addPropertiesToUpdate(matchContext, root, query, cb);
// Add updatable auto-populated parameters
entity.getPersistentProperties().stream().filter(p -> p != null && p.findAnnotation(AutoPopulated.class).map(ap -> ap.getRequiredValue(AutoPopulated.UPDATEABLE, Boolean.class)).orElse(false)).forEach(p -> query.set(p.getName(), cb.parameter((ParameterElement) null)));
if (entity.getVersion() != null) {
if (((AbstractPersistentEntityCriteriaUpdate<T>) query).hasVersionRestriction()) {
query.set(entity.getVersion().getName(), cb.parameter((ParameterElement) null));
}
}
if (((AbstractPersistentEntityCriteriaUpdate<T>) query).getUpdateValues().isEmpty()) {
throw new MatchFailedException("At least one parameter required to update");
}
}
Aggregations