Skip to content

Commit

Permalink
Correct
Browse files Browse the repository at this point in the history
  • Loading branch information
dstepanov committed Jan 30, 2025
1 parent a956821 commit 8632e96
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,14 @@ protected void appendPropertyProjection(QueryPropertyPath propertyPath) {
}

@Override
protected void appendAssociationProjection(Association association, PersistentPropertyPath propertyPath) {
String joinedPath = propertyPath.getPath();
protected void appendAssociationProjection(PersistentAssociationPath associationPath) {
String joinedPath = associationPath.getPath();
if (!queryState.isJoined(joinedPath)) {
query.setLength(query.length() - 1);
return;
}
String joinAlias = queryState.getJoinAlias(propertyPath.getPath());
selectAllColumns(AnnotationMetadata.EMPTY_METADATA, association.getAssociatedEntity(), joinAlias);
String joinAlias = queryState.getJoinAlias(associationPath.getPath());
selectAllColumns(AnnotationMetadata.EMPTY_METADATA, associationPath.getAssociation().getAssociatedEntity(), joinAlias);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.micronaut.data.jdbc.h2.one2one.select;

import io.micronaut.data.annotation.AutoPopulated;
import io.micronaut.data.annotation.Id;
import io.micronaut.data.annotation.MappedEntity;

import java.util.UUID;

@MappedEntity
public class MyEmbedded {

@Id
@AutoPopulated
private UUID id;

private String someProp;

public UUID getId() {
return id;
}

public void setId(UUID id) {
this.id = id;
}

public String getSomeProp() {
return someProp;
}

public void setSomeProp(String someProp) {
this.someProp = someProp;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package io.micronaut.data.jdbc.h2.one2one.select;

import io.micronaut.core.annotation.Nullable;
import io.micronaut.data.annotation.AutoPopulated;
import io.micronaut.data.annotation.Id;
import io.micronaut.data.annotation.MappedEntity;
import io.micronaut.data.annotation.Relation;

import java.util.UUID;

@MappedEntity
public class MyOrder {

@Id
@AutoPopulated
private UUID orderId;

@Nullable
@Relation(value = Relation.Kind.ONE_TO_ONE)
private MyEmbedded embedded;

public UUID getOrderId() {
return orderId;
}

public void setOrderId(UUID orderId) {
this.orderId = orderId;
}

public MyEmbedded getEmbedded() {
return embedded;
}

public void setEmbedded(MyEmbedded embedded) {
this.embedded = embedded;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.micronaut.data.jdbc.h2.one2one.select;

import io.micronaut.core.annotation.NonNull;
import io.micronaut.data.annotation.Join;
import io.micronaut.data.annotation.repeatable.JoinSpecifications;
import io.micronaut.data.jdbc.annotation.JdbcRepository;
import io.micronaut.data.model.Page;
import io.micronaut.data.model.Pageable;
import io.micronaut.data.model.query.builder.sql.Dialect;
import io.micronaut.data.repository.CrudRepository;
import io.micronaut.data.repository.jpa.criteria.PredicateSpecification;

import java.util.UUID;

@JdbcRepository(dialect = Dialect.H2)
public interface MyOrderRepository extends CrudRepository<MyOrder, UUID> {
@NonNull
@JoinSpecifications({
@Join(value = "embedded", type = Join.Type.LEFT_FETCH)
})
Page<MyOrder> findAll(PredicateSpecification<MyOrder> spec, Pageable pageable);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.micronaut.data.jdbc.h2.one2one.select

import io.micronaut.data.jdbc.h2.H2DBProperties
import io.micronaut.data.model.Pageable
import io.micronaut.data.model.Sort
import io.micronaut.data.repository.jpa.criteria.PredicateSpecification
import io.micronaut.test.extensions.spock.annotation.MicronautTest
import jakarta.inject.Inject
import spock.lang.Specification

@H2DBProperties
@MicronautTest(transactional = false)
class OneToOneProjectionSpec extends Specification {

@Inject
MyOrderRepository orderRepository

void findAll_withPageableSort_andSearch() {
given:
Sort.Order.Direction sortDirection = Sort.Order.Direction.ASC
Pageable pageable = Pageable.UNPAGED.order(new Sort.Order("embedded.someProp", sortDirection, false))
PredicateSpecification<MyOrder> predicate = null
when:
orderRepository.findAll(predicate, pageable)
then:
noExceptionThrown()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,21 @@ public String getPath() {
return path;
}

/**
* @return The associations path
*/
@NonNull
public String getAssociationsPath() {
if (associations.isEmpty()) {
return "";
}
StringJoiner joiner = new StringJoiner(".");
for (Association association : associations) {
joiner.add(association.getName());
}
return joiner.toString();
}

/**
* @return The array path
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2512,6 +2512,8 @@ public void visit(io.micronaut.data.model.jpa.criteria.PersistentPropertyPath<?>
} else {
query.setLength(query.length() - 1);
}
} else if (!propertyPath.getAssociations().isEmpty() && queryState.isJoined(propertyPath.getAssociationsPath())) {
appendPropertyProjection(findProperty(propertyPath.getPath()));
} else {
appendCompoundPropertyProjection(propertyPath);
}
Expand All @@ -2520,7 +2522,7 @@ public void visit(io.micronaut.data.model.jpa.criteria.PersistentPropertyPath<?>
query.append(DISTINCT);
}
if (property instanceof Association association && !property.isEmbedded()) {
appendAssociationProjection(association, propertyPath);
appendAssociationProjection(new PersistentAssociationPath(propertyPath.getAssociations(), association));
} else {
appendPropertyProjection(findProperty(propertyPath.getPath()));
}
Expand Down Expand Up @@ -2681,7 +2683,21 @@ protected void appendCompoundPropertyProjection(PersistentPropertyPath propertyP
@Internal
protected void appendCompoundAssociationProjection(PersistentAssociationPath propertyPath) {
if (!query.isEmpty() && query.charAt(query.length() - 1) == ',') {
// Strip last .
// Strip last ,
query.setLength(query.length() - 1);
}
selectAllColumnsFromJoinPaths(queryState.baseQueryDefinition().getJoinPaths(), null);
}

/**
* Appends the compound (part of entity or DTO) association projection.
*
* @param propertyPath The property path
*/
@Internal
protected void appendCompoundProjection(PersistentPropertyPath propertyPath) {
if (!query.isEmpty() && query.charAt(query.length() - 1) == ',') {
// Strip last ,
query.setLength(query.length() - 1);
}
selectAllColumnsFromJoinPaths(queryState.baseQueryDefinition().getJoinPaths(), null);
Expand Down Expand Up @@ -2737,19 +2753,17 @@ protected void appendPropertyProjection(QueryPropertyPath propertyPath) {
/**
* Appends selection projection for the property which is association.
*
* @param association the persistent property
* @param propertyPath the persistent property path
* @param associationPath the persistent property path
*/
protected void appendAssociationProjection(Association association,
PersistentPropertyPath propertyPath) {
String joinedPath = propertyPath.getPath();
protected void appendAssociationProjection(PersistentAssociationPath associationPath) {
String joinedPath = associationPath.getPath();
if (!queryState.isJoined(joinedPath)) {
query.setLength(query.length() - 1);
return;
}
String joinAlias = queryState.findJoinAlias(propertyPath.getPath());
String joinAlias = queryState.findJoinAlias(associationPath.getPath());

selectAllColumns(AnnotationMetadata.EMPTY_METADATA, association.getAssociatedEntity(), joinAlias);
selectAllColumns(AnnotationMetadata.EMPTY_METADATA, associationPath.getAssociation().getAssociatedEntity(), joinAlias);

Collection<JoinPath> joinPaths = queryState.baseQueryDefinition().getJoinPaths();
List<JoinPath> newJoinPaths = new ArrayList<>(joinPaths.size());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,9 +379,10 @@ private <K> CriteriaQuery<Tuple> createSelectIdsCriteriaQuery(MethodInvocationCo
// We need to select all ordered properties from ORDER BY for DISTINCT to work properly
for (Sort.Order order : sort.getOrderBy()) {
Path<?> path = root;
for (String next : StringUtils.splitOmitEmptyStrings(order.getProperty(), '.')) {
if (path instanceof From<?, ?> from) {
path = from.join(next);
for (Iterator<String> iterator = StringUtils.splitOmitEmptyStrings(order.getProperty(), '.').iterator(); iterator.hasNext(); ) {
String next = iterator.next();
if (iterator.hasNext()) {
path = ((From<?, ?>) path).join(next);
} else {
path = path.get(next);
}
Expand Down Expand Up @@ -587,9 +588,10 @@ private List<Order> getOrders(Sort sort, Root<?> root, CriteriaBuilder cb) {
List<Order> orders = new ArrayList<>();
for (Sort.Order order : sort.getOrderBy()) {
Path<?> path = root;
for (String next : StringUtils.splitOmitEmptyStrings(order.getProperty(), '.')) {
if (path instanceof From<?, ?> from) {
path = from.join(next);
for (Iterator<String> iterator = StringUtils.splitOmitEmptyStrings(order.getProperty(), '.').iterator(); iterator.hasNext(); ) {
String next = iterator.next();
if (iterator.hasNext()) {
path = ((From<?, ?>) path).join(next);
} else {
path = path.get(next);
}
Expand Down

0 comments on commit 8632e96

Please sign in to comment.