Skip to content

Commit b098652

Browse files
gregturnschauder
authored andcommitted
Allow JpaParametersParameterAccessor to extract dates from parameters.
This allows the Hibernate variant (HibernateJpaParametersParameterAccessor) to potentially unwrap TypedParameterValue. Closes #2857 Original pull request #2859
1 parent ff1f8bf commit b098652

File tree

4 files changed

+48
-16
lines changed

4 files changed

+48
-16
lines changed

spring-data-jpa/src/main/java/org/springframework/data/jpa/provider/HibernateJpaParametersParameterAccessor.java

+21-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
import jakarta.persistence.EntityManager;
1919

20+
import java.util.Date;
21+
2022
import org.hibernate.engine.spi.SessionFactoryImplementor;
2123
import org.hibernate.query.TypedParameterValue;
2224
import org.hibernate.type.BasicTypeRegistry;
@@ -36,6 +38,7 @@
3638
* @author Cedomir Igaly
3739
* @author Robert Wilson
3840
* @author Oliver Drotbohm
41+
* @author Greg Turnquist
3942
* @since 2.7
4043
*/
4144
class HibernateJpaParametersParameterAccessor extends JpaParametersParameterAccessor {
@@ -53,9 +56,9 @@ class HibernateJpaParametersParameterAccessor extends JpaParametersParameterAcce
5356

5457
super(parameters, values);
5558

56-
this.typeHelper = em.getEntityManagerFactory()
57-
.unwrap(SessionFactoryImplementor.class)
58-
.getTypeConfiguration()
59+
this.typeHelper = em.getEntityManagerFactory() //
60+
.unwrap(SessionFactoryImplementor.class) //
61+
.getTypeConfiguration() //
5962
.getBasicTypeRegistry();
6063
}
6164

@@ -78,4 +81,19 @@ public Object getValue(Parameter parameter) {
7881

7982
return new TypedParameterValue<>(type, null);
8083
}
84+
85+
/**
86+
* For Hibernate, check if the incoming value is wrapped inside a {@link TypedParameterValue} before extracting and
87+
* casting the {@link Date}.
88+
*
89+
* @param extractedValue
90+
* @since 3.1
91+
*/
92+
@Override
93+
public Date extractDate(Object extractedValue) {
94+
95+
return (extractedValue instanceof TypedParameterValue<?> typedParameterValue)
96+
? (Date) typedParameterValue.getValue()
97+
: (Date) extractedValue;
98+
}
8199
}

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpaParametersParameterAccessor.java

+14
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package org.springframework.data.jpa.repository.query;
1717

18+
import java.util.Date;
19+
1820
import org.springframework.data.jpa.repository.query.JpaParameters.JpaParameter;
1921
import org.springframework.data.repository.query.Parameter;
2022
import org.springframework.data.repository.query.Parameters;
@@ -27,6 +29,7 @@
2729
*
2830
* @author Jens Schauder
2931
* @author Mark Paluch
32+
* @author Greg Turnquist
3033
*/
3134
public class JpaParametersParameterAccessor extends ParametersParameterAccessor {
3235

@@ -49,4 +52,15 @@ public <T> T getValue(Parameter parameter) {
4952
public Object[] getValues() {
5053
return super.getValues();
5154
}
55+
56+
/**
57+
* For general JPA providers, simply pass through the extracted value, casting it as a {@link Date}.
58+
*
59+
* @param extractedValue
60+
* @since 3.1
61+
*/
62+
public Date extractDate(Object extractedValue) {
63+
return (Date) extractedValue;
64+
}
65+
5266
}

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/QueryParameterSetter.java

+3-6
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616
package org.springframework.data.jpa.repository.query;
1717

18-
import static org.springframework.data.jpa.repository.query.QueryParameterSetter.ErrorHandling.LENIENT;
18+
import static org.springframework.data.jpa.repository.query.QueryParameterSetter.ErrorHandling.*;
1919

2020
import jakarta.persistence.Parameter;
2121
import jakarta.persistence.Query;
@@ -32,7 +32,6 @@
3232

3333
import org.apache.commons.logging.Log;
3434
import org.apache.commons.logging.LogFactory;
35-
import org.hibernate.query.TypedParameterValue;
3635
import org.springframework.lang.Nullable;
3736
import org.springframework.util.Assert;
3837

@@ -82,11 +81,9 @@ public void setParameter(BindableQuery query, JpaParametersParameterAccessor acc
8281

8382
if (temporalType != null) {
8483

85-
var extractedValue = valueExtractor.apply(accessor);
84+
Object extractedValue = valueExtractor.apply(accessor);
8685

87-
final Date value = (extractedValue instanceof TypedParameterValue<?> typedParameterValue)
88-
? (Date) typedParameterValue.getValue()
89-
: (Date) extractedValue;
86+
final Date value = accessor.extractDate(extractedValue);
9087

9188
// One would think we can simply use parameter to identify the parameter we want to set.
9289
// But that does not work with list valued parameters. At least Hibernate tries to bind them by name.

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/NamedOrIndexedQueryParameterSetterUnitTests.java

+10-7
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@
1515
*/
1616
package org.springframework.data.jpa.repository.query;
1717

18-
import static java.util.Arrays.*;
1918
import static jakarta.persistence.TemporalType.*;
19+
import static java.util.Arrays.*;
2020
import static org.mockito.ArgumentMatchers.*;
2121
import static org.mockito.Mockito.*;
2222
import static org.springframework.data.jpa.repository.query.QueryParameterSetter.ErrorHandling.*;
2323

24+
import jakarta.persistence.Parameter;
25+
import jakarta.persistence.Query;
26+
import jakarta.persistence.TemporalType;
27+
import jakarta.persistence.criteria.ParameterExpression;
2428
import lombok.Value;
2529

2630
import java.util.Arrays;
@@ -29,11 +33,6 @@
2933
import java.util.List;
3034
import java.util.function.Function;
3135

32-
import jakarta.persistence.Parameter;
33-
import jakarta.persistence.Query;
34-
import jakarta.persistence.TemporalType;
35-
import jakarta.persistence.criteria.ParameterExpression;
36-
3736
import org.assertj.core.api.SoftAssertions;
3837
import org.junit.jupiter.api.BeforeEach;
3938
import org.junit.jupiter.api.Test;
@@ -65,7 +64,11 @@ class NamedOrIndexedQueryParameterSetterUnitTests {
6564
void before() {
6665

6766
JpaParametersParameterAccessor accessor = mock(JpaParametersParameterAccessor.class);
68-
when(accessor.getValues()).thenReturn(new Object[] { new Date() });
67+
68+
Date testDate = new Date();
69+
70+
when(accessor.getValues()).thenReturn(new Object[] { testDate });
71+
when(accessor.extractDate(testDate)).thenReturn(testDate);
6972

7073
this.methodArguments = accessor;
7174
}

0 commit comments

Comments
 (0)