From 6005b2c5fc500f5f641618a34ae38bbabf4e46db Mon Sep 17 00:00:00 2001 From: radovanradic Date: Mon, 16 Sep 2024 12:37:49 +0200 Subject: [PATCH] Fix binding embeded id parameter --- .../data/jdbc/h2/H2EmbeddedIdSpec.groovy | 32 +++++++++++++++++++ .../data/jdbc/h2/ShipmentRepository.java | 3 +- .../impl/DefaultParameterExpression.java | 12 ++++++- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/data-jdbc/src/test/groovy/io/micronaut/data/jdbc/h2/H2EmbeddedIdSpec.groovy b/data-jdbc/src/test/groovy/io/micronaut/data/jdbc/h2/H2EmbeddedIdSpec.groovy index 4a5151d3f05..5a1f3e319fb 100644 --- a/data-jdbc/src/test/groovy/io/micronaut/data/jdbc/h2/H2EmbeddedIdSpec.groovy +++ b/data-jdbc/src/test/groovy/io/micronaut/data/jdbc/h2/H2EmbeddedIdSpec.groovy @@ -21,9 +21,14 @@ import io.micronaut.data.jdbc.annotation.JdbcRepository import io.micronaut.data.model.Sort import io.micronaut.data.model.query.builder.sql.Dialect import io.micronaut.data.repository.CrudRepository +import io.micronaut.data.repository.jpa.criteria.UpdateSpecification import io.micronaut.data.tck.entities.Shipment import io.micronaut.data.tck.entities.ShipmentId import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.persistence.criteria.CriteriaBuilder +import jakarta.persistence.criteria.CriteriaUpdate +import jakarta.persistence.criteria.Predicate +import jakarta.persistence.criteria.Root import spock.lang.Specification import jakarta.inject.Inject @@ -99,6 +104,33 @@ class H2EmbeddedIdSpec extends Specification { then:"all is correct" all.size() == 2 + when:"Update specification by embedded id" + repository.updateAll(new UpdateSpecification() { + @Override + Predicate toPredicate(Root root, CriteriaUpdate query, CriteriaBuilder criteriaBuilder) { + query.set("field", "test3-updated") + return criteriaBuilder.equal(root.get("shipmentId"), id3) + } + }) + def updatedShipment = repository.findById(id3).orElse(null) + then:"Update is successful" + updatedShipment + updatedShipment.field == "test3-updated" + + when:"Update specification by embedded id parts" + repository.updateAll(new UpdateSpecification() { + @Override + Predicate toPredicate(Root root, CriteriaUpdate query, CriteriaBuilder criteriaBuilder) { + query.set("field", "test3") + return criteriaBuilder.and(criteriaBuilder.equal(root.join("shipmentId").get("country"), id3.country), + criteriaBuilder.equal(root.join("shipmentId").get("city"), id3.city)) + } + }) + updatedShipment = repository.findById(id3).orElse(null) + then:"Update is successful" + updatedShipment + updatedShipment.field == "test3" + when:"Find by country" def foundByCountry = repository.findByShipmentIdCountry("g") diff --git a/data-jdbc/src/test/java/io/micronaut/data/jdbc/h2/ShipmentRepository.java b/data-jdbc/src/test/java/io/micronaut/data/jdbc/h2/ShipmentRepository.java index bd9157a1706..b95be4d9a82 100644 --- a/data-jdbc/src/test/java/io/micronaut/data/jdbc/h2/ShipmentRepository.java +++ b/data-jdbc/src/test/java/io/micronaut/data/jdbc/h2/ShipmentRepository.java @@ -17,6 +17,7 @@ import io.micronaut.data.jdbc.annotation.JdbcRepository; import io.micronaut.data.repository.PageableRepository; +import io.micronaut.data.repository.jpa.JpaSpecificationExecutor; import io.micronaut.data.tck.entities.Shipment; import io.micronaut.data.tck.entities.ShipmentId; import io.micronaut.data.model.query.builder.sql.Dialect; @@ -24,7 +25,7 @@ import java.util.List; @JdbcRepository(dialect = Dialect.H2) -public interface ShipmentRepository extends PageableRepository { +public interface ShipmentRepository extends PageableRepository, JpaSpecificationExecutor { Shipment findByShipmentIdCountry(String country); diff --git a/data-model/src/main/java/io/micronaut/data/model/jpa/criteria/impl/DefaultParameterExpression.java b/data-model/src/main/java/io/micronaut/data/model/jpa/criteria/impl/DefaultParameterExpression.java index 732d7e793ce..384023f1278 100644 --- a/data-model/src/main/java/io/micronaut/data/model/jpa/criteria/impl/DefaultParameterExpression.java +++ b/data-model/src/main/java/io/micronaut/data/model/jpa/criteria/impl/DefaultParameterExpression.java @@ -18,9 +18,12 @@ import io.micronaut.core.annotation.Internal; import io.micronaut.core.annotation.NonNull; import io.micronaut.core.annotation.Nullable; +import io.micronaut.core.beans.BeanWrapper; +import io.micronaut.core.type.Argument; import io.micronaut.data.model.DataType; import io.micronaut.data.model.PersistentPropertyPath; import io.micronaut.data.model.query.builder.QueryParameterBinding; +import io.micronaut.data.model.runtime.RuntimePersistentEntity; /** * The default parameter expression implementation. @@ -48,6 +51,13 @@ public QueryParameterBinding bind(BindingContext bindingContext) { if (outgoingQueryParameterProperty == null) { return new SimpleParameterBinding(name, DataType.forType(paramClass), bindingContext.isExpandable(), value); } - return new PropertyPathParameterBinding(name, outgoingQueryParameterProperty, bindingContext.isExpandable(), value); + Object parameterValue = value; + if (value != null && outgoingQueryParameterProperty.getProperty().getOwner().isEmbeddable()) { + RuntimePersistentEntity runtimePersistentEntity = (RuntimePersistentEntity) outgoingQueryParameterProperty.getProperty().getOwner(); + if (runtimePersistentEntity.getIntrospection().getBeanType().isAssignableFrom(value.getClass())) { + parameterValue = BeanWrapper.getWrapper(parameterValue).getRequiredProperty(outgoingQueryParameterProperty.getProperty().getName(), Argument.OBJECT_ARGUMENT); + } + } + return new PropertyPathParameterBinding(name, outgoingQueryParameterProperty, bindingContext.isExpandable(), parameterValue); } }