Skip to content

Commit

Permalink
fix(core): Types projections (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
JoseLion authored Feb 26, 2024
1 parent 6e1b8c0 commit 2a42bda
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.github.joselion.springr2dbcrelationships.processors;

import static java.util.Arrays.stream;
import static java.util.function.Predicate.isEqual;
import static java.util.function.Predicate.not;
import static java.util.stream.Collectors.joining;
Expand All @@ -11,6 +12,7 @@
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.IntStream;
Expand Down Expand Up @@ -66,13 +68,18 @@ public Mono<List<?>> populate(final ManyToMany annotation, final Field field) {
.or(() -> this.createdColumnOf(innerType))
.map(sortBy -> "ORDER BY b.%s %s".formatted(sortBy, sortIn))
.orElse("");
final var columns = stream(innerType.getDeclaredFields())
.map(this::columnNameOrNull)
.filter(Objects::nonNull)
.map("b."::concat)
.collect(joining(", "));
final var partialStatement = """
SELECT DISTINCT b.* FROM %s AS b
SELECT DISTINCT %s FROM %s AS b
LEFT JOIN %s AS j ON j.%s = b.%s
WHERE j.%s = $1
%s
"""
.formatted(innerTable, "%s", linkedBy, innerId, mappedBy, orderBy);
.formatted(columns, innerTable, "%s", linkedBy, innerId, mappedBy, orderBy);

return Mono.just(annotation)
.map(ManyToMany::joinTable)
Expand Down Expand Up @@ -105,8 +112,8 @@ public Mono<List<?>> populate(final ManyToMany annotation, final Field field) {

@Override
public Mono<List<?>> persist(final ManyToMany annotation, final Field field) {
final var entityType = this.entity.getClass();
final var innerType = Reflect.innerTypeOf(field);
final var entityType = this.domainFor(this.entity.getClass());
final var innerType = this.domainFor(Reflect.innerTypeOf(field));
final var entityTable = this.tableNameOf(entityType);
final var innerTable = this.tableNameOf(innerType);
final var mappedBy = Optional.of(annotation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ public record ManyToOneProcessor(

@Override
public Mono<Object> populate(final ManyToOne annotation, final Field field) {
final var fieldType = field.getType();
final var fieldProjection = field.getType();
final var fieldType = this.domainFor(fieldProjection);
final var foreignKey = Optional.of(annotation)
.map(ManyToOne::foreignKey)
.filter(not(String::isBlank))
Expand All @@ -41,25 +42,26 @@ public Mono<Object> populate(final ManyToOne annotation, final Field field) {
final var keyValue = Optional.of(this.entity)
.map(Reflect.getter(foreignField))
.orElseThrow(() -> {
final var entityType = this.domainFor(this.entity.getClass());
final var message = "Entity <%s> is missing foreign key in field: %s".formatted(
this.entity.getClass().getName(),
entityType.getName(),
foreignField
);

return RelationshipException.of(message);
});

return this.template
.select(this.domainFor(fieldType))
.as(fieldType)
.select(fieldType)
.as(fieldProjection)
.matching(query(where(parentId).is(keyValue)))
.one()
.map(Commons::cast);
}

@Override
public Mono<Object> persist(final ManyToOne annotation, final Field field) {
final var fieldType = field.getType();
final var fieldType = this.domainFor(field.getType());
final var foreignKey = Optional.of(annotation)
.map(ManyToOne::foreignKey)
.filter(not(String::isBlank))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ public record OneToManyProcessor(

@Override
public Mono<List<?>> populate(final OneToMany annotation, final Field field) {
final var innerType = Reflect.innerTypeOf(field);
final var innerProjection = Reflect.innerTypeOf(field);
final var innerType = this.domainFor(innerProjection);
final var mappedBy = Optional.of(annotation)
.map(OneToMany::mappedBy)
.filter(not(String::isBlank))
Expand All @@ -51,8 +52,8 @@ public Mono<List<?>> populate(final OneToMany annotation, final Field field) {
.mapNotNull(this::idValueOf)
.flatMap(entityId ->
this.template
.select(this.domainFor(innerType))
.as(innerType)
.select(innerType)
.as(innerProjection)
.matching(query(where(mappedBy).is(entityId)).sort(byColumn))
.all()
.collectList()
Expand All @@ -64,7 +65,7 @@ public Mono<List<?>> persist(final OneToMany annotation, final Field field) {
return Mono.just(this.entity)
.mapNotNull(this::idValueOf)
.flatMap(entityId -> {
final var innerType = Reflect.innerTypeOf(field);
final var innerType = this.domainFor(Reflect.innerTypeOf(field));
final var mappedBy = Optional.of(annotation)
.map(OneToMany::mappedBy)
.filter(not(String::isBlank))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ public record OneToOneProcessor(

@Override
public Mono<Object> populate(final OneToOne annotation, final Field field) {
final var fieldType = field.getType();
final var fieldProjection = field.getType();
final var fieldType = this.domainFor(fieldProjection);
final var isBackReference = Optional.of(annotation)
.filter(OneToOne::backReference)
.isPresent();
Expand All @@ -52,17 +53,18 @@ public Mono<Object> populate(final OneToOne annotation, final Field field) {
final var fkValue = Optional.of(this.entity)
.map(Reflect.getter(mappedField))
.orElseThrow(() -> {
final var entityType = this.domainFor(this.entity.getClass());
final var message = "Entity <%s> is missing foreign key in field: %s".formatted(
this.entity.getClass().getName(),
entityType.getName(),
mappedField
);

return RelationshipException.of(message);
});

return this.template
.select(this.domainFor(fieldType))
.as(fieldType)
.select(fieldType)
.as(fieldProjection)
.matching(query(where(parentId).is(fkValue)))
.one()
.map(Commons::cast);
Expand All @@ -72,8 +74,8 @@ public Mono<Object> populate(final OneToOne annotation, final Field field) {
.mapNotNull(this::idValueOf)
.flatMap(entityId ->
this.template
.select(this.domainFor(fieldType))
.as(fieldType)
.select(fieldType)
.as(fieldProjection)
.matching(query(where(mappedBy).is(entityId)))
.one()
);
Expand All @@ -84,8 +86,9 @@ public Mono<Object> persist(final OneToOne annotation, final Field field) {
return Mono.just(this.entity)
.mapNotNull(this::idValueOf)
.flatMap(entityId -> {
final var fieldType = field.getType();
final var entityName = this.entity.getClass().getSimpleName();
final var fieldType = this.domainFor(field.getType());
final var entityType = this.domainFor(this.entity.getClass());
final var entityName = entityType.getSimpleName();
final var mappedBy = Optional.of(annotation)
.map(OneToOne::mappedBy)
.filter(not(String::isBlank))
Expand All @@ -100,7 +103,7 @@ public Mono<Object> persist(final OneToOne annotation, final Field field) {
.flatMap(this::upsert)
.switchIfEmpty(
this.template
.delete(this.domainFor(fieldType))
.delete(fieldType)
.matching(query(where(mappedBy).is(entityId)))
.all()
.then(Mono.empty())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,4 +261,27 @@ default String columnNameOf(final Field field) {
.getColumnName()
.getReference();
}

/**
* Returns the column name representation of a field or null if the
* persistent property does not exist.
*
* @param field the field that maps the column
* @return the column name of the field or null
*/
@Nullable
default String columnNameOrNull(final Field field) {
final var fieldName = field.getName();
final var targetType = field.getDeclaringClass();
final var entity = this.template()
.getConverter()
.getMappingContext()
.getRequiredPersistentEntity(targetType);

return Optional.of(fieldName)
.map(entity::getPersistentProperty)
.map(RelationalPersistentProperty::getColumnName)
.map(SqlIdentifier::getReference)
.orElse(null);
}
}

0 comments on commit 2a42bda

Please sign in to comment.