diff --git a/pom.xml b/pom.xml index c77686453f..2e1d94556f 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-jpa-parent - 3.1.0-SNAPSHOT + 3.1.0-gh-2857-SNAPSHOT pom Spring Data JPA Parent diff --git a/spring-data-envers/pom.xml b/spring-data-envers/pom.xml index db915d7c3b..4dfabd0bcb 100755 --- a/spring-data-envers/pom.xml +++ b/spring-data-envers/pom.xml @@ -5,12 +5,12 @@ org.springframework.data spring-data-envers - 3.1.0-SNAPSHOT + 3.1.0-gh-2857-SNAPSHOT org.springframework.data spring-data-jpa-parent - 3.1.0-SNAPSHOT + 3.1.0-gh-2857-SNAPSHOT ../pom.xml diff --git a/spring-data-jpa-distribution/pom.xml b/spring-data-jpa-distribution/pom.xml index a5cb2f09b5..3021fd1bd5 100644 --- a/spring-data-jpa-distribution/pom.xml +++ b/spring-data-jpa-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-jpa-parent - 3.1.0-SNAPSHOT + 3.1.0-gh-2857-SNAPSHOT ../pom.xml diff --git a/spring-data-jpa/pom.xml b/spring-data-jpa/pom.xml index 27313e9e3c..4db95b726f 100644 --- a/spring-data-jpa/pom.xml +++ b/spring-data-jpa/pom.xml @@ -6,7 +6,7 @@ org.springframework.data spring-data-jpa - 3.1.0-SNAPSHOT + 3.1.0-gh-2857-SNAPSHOT Spring Data JPA Spring Data module for JPA repositories. @@ -15,7 +15,7 @@ org.springframework.data spring-data-jpa-parent - 3.1.0-SNAPSHOT + 3.1.0-gh-2857-SNAPSHOT ../pom.xml diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/provider/HibernateJpaParametersParameterAccessor.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/provider/HibernateJpaParametersParameterAccessor.java index 6b9f2628c2..012971ffca 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/provider/HibernateJpaParametersParameterAccessor.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/provider/HibernateJpaParametersParameterAccessor.java @@ -17,6 +17,8 @@ import jakarta.persistence.EntityManager; +import java.util.Date; + import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.query.TypedParameterValue; import org.hibernate.type.BasicTypeRegistry; @@ -36,6 +38,7 @@ * @author Cedomir Igaly * @author Robert Wilson * @author Oliver Drotbohm + * @author Greg Turnquist * @since 2.7 */ class HibernateJpaParametersParameterAccessor extends JpaParametersParameterAccessor { @@ -53,9 +56,9 @@ class HibernateJpaParametersParameterAccessor extends JpaParametersParameterAcce super(parameters, values); - this.typeHelper = em.getEntityManagerFactory() - .unwrap(SessionFactoryImplementor.class) - .getTypeConfiguration() + this.typeHelper = em.getEntityManagerFactory() // + .unwrap(SessionFactoryImplementor.class) // + .getTypeConfiguration() // .getBasicTypeRegistry(); } @@ -78,4 +81,19 @@ public Object getValue(Parameter parameter) { return new TypedParameterValue<>(type, null); } + + /** + * For Hibernate, check if the incoming value is wrapped inside a {@link TypedParameterValue} before extracting and + * casting the {@link Date}. + * + * @param extractedValue + * @since 3.1 + */ + @Override + public Date extractDate(Object extractedValue) { + + return (extractedValue instanceof TypedParameterValue typedParameterValue) + ? (Date) typedParameterValue.getValue() + : (Date) extractedValue; + } } diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaParametersParameterAccessor.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaParametersParameterAccessor.java index fb1ff1b8b6..ea025d3cc9 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaParametersParameterAccessor.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaParametersParameterAccessor.java @@ -15,6 +15,8 @@ */ package org.springframework.data.jpa.repository.query; +import java.util.Date; + import org.springframework.data.jpa.repository.query.JpaParameters.JpaParameter; import org.springframework.data.repository.query.Parameter; import org.springframework.data.repository.query.Parameters; @@ -27,6 +29,7 @@ * * @author Jens Schauder * @author Mark Paluch + * @author Greg Turnquist */ public class JpaParametersParameterAccessor extends ParametersParameterAccessor { @@ -49,4 +52,15 @@ public T getValue(Parameter parameter) { public Object[] getValues() { return super.getValues(); } + + /** + * For general JPA providers, simply pass through the extracted value, casting it as a {@link Date}. + * + * @param extractedValue + * @since 3.1 + */ + public Date extractDate(Object extractedValue) { + return (Date) extractedValue; + } + } diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/QueryParameterSetter.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/QueryParameterSetter.java index 23ff9deed1..d16322db14 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/QueryParameterSetter.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/QueryParameterSetter.java @@ -15,7 +15,7 @@ */ package org.springframework.data.jpa.repository.query; -import static org.springframework.data.jpa.repository.query.QueryParameterSetter.ErrorHandling.LENIENT; +import static org.springframework.data.jpa.repository.query.QueryParameterSetter.ErrorHandling.*; import jakarta.persistence.Parameter; import jakarta.persistence.Query; @@ -32,7 +32,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.hibernate.query.TypedParameterValue; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -82,11 +81,9 @@ public void setParameter(BindableQuery query, JpaParametersParameterAccessor acc if (temporalType != null) { - var extractedValue = valueExtractor.apply(accessor); + Object extractedValue = valueExtractor.apply(accessor); - final Date value = (extractedValue instanceof TypedParameterValue typedParameterValue) - ? (Date) typedParameterValue.getValue() - : (Date) extractedValue; + final Date value = accessor.extractDate(extractedValue); // One would think we can simply use parameter to identify the parameter we want to set. // But that does not work with list valued parameters. At least Hibernate tries to bind them by name. diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/NamedOrIndexedQueryParameterSetterUnitTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/NamedOrIndexedQueryParameterSetterUnitTests.java index 9440a81b51..6de4cc64fa 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/NamedOrIndexedQueryParameterSetterUnitTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/NamedOrIndexedQueryParameterSetterUnitTests.java @@ -15,12 +15,16 @@ */ package org.springframework.data.jpa.repository.query; -import static java.util.Arrays.*; import static jakarta.persistence.TemporalType.*; +import static java.util.Arrays.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import static org.springframework.data.jpa.repository.query.QueryParameterSetter.ErrorHandling.*; +import jakarta.persistence.Parameter; +import jakarta.persistence.Query; +import jakarta.persistence.TemporalType; +import jakarta.persistence.criteria.ParameterExpression; import lombok.Value; import java.util.Arrays; @@ -29,11 +33,6 @@ import java.util.List; import java.util.function.Function; -import jakarta.persistence.Parameter; -import jakarta.persistence.Query; -import jakarta.persistence.TemporalType; -import jakarta.persistence.criteria.ParameterExpression; - import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -65,7 +64,11 @@ class NamedOrIndexedQueryParameterSetterUnitTests { void before() { JpaParametersParameterAccessor accessor = mock(JpaParametersParameterAccessor.class); - when(accessor.getValues()).thenReturn(new Object[] { new Date() }); + + Date testDate = new Date(); + + when(accessor.getValues()).thenReturn(new Object[] { testDate }); + when(accessor.extractDate(testDate)).thenReturn(testDate); this.methodArguments = accessor; }