Skip to content

Commit dfb9d7a

Browse files
committed
Polishing.
Replaced type check by method providing the correct JpaParameterParameterAccessor. Formatting. See #2370 Original pull request #2461
1 parent 3c804cf commit dfb9d7a

File tree

5 files changed

+92
-80
lines changed

5 files changed

+92
-80
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2022 the original author or authors.
2+
* Copyright 2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -13,26 +13,29 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package org.springframework.data.jpa.repository.query;
16+
package org.springframework.data.jpa.provider;
1717

1818
import javax.persistence.EntityManager;
1919

2020
import org.hibernate.Session;
2121
import org.hibernate.TypeHelper;
2222
import org.hibernate.jpa.TypedParameterValue;
2323
import org.hibernate.type.Type;
24+
import org.springframework.data.jpa.repository.query.JpaParametersParameterAccessor;
2425
import org.springframework.data.repository.query.Parameter;
2526
import org.springframework.data.repository.query.Parameters;
2627
import org.springframework.data.repository.query.ParametersParameterAccessor;
2728

2829
/**
29-
* {@link org.springframework.data.repository.query.ParameterAccessor} based on an {@link Parameters} instance.
30-
* In addition to the {@link JpaParametersParameterAccessor} functions, the bindable value is provided by
31-
* fetching the method type when there is null.
30+
* {@link org.springframework.data.repository.query.ParameterAccessor} based on an {@link Parameters} instance. In
31+
* addition to the {@link JpaParametersParameterAccessor} functions, the bindable value is provided by fetching the
32+
* method type when there is null.
3233
*
3334
* @author Wonchul Heo
35+
* @author Jens Schauder
36+
* @since 2.7
3437
*/
35-
public class HibernateJpaParametersParameterAccessor extends JpaParametersParameterAccessor {
38+
class HibernateJpaParametersParameterAccessor extends JpaParametersParameterAccessor {
3639

3740
private final TypeHelper typeHelper;
3841

@@ -44,25 +47,25 @@ public class HibernateJpaParametersParameterAccessor extends JpaParametersParame
4447
* @param em must not be {@literal null}.
4548
*/
4649
HibernateJpaParametersParameterAccessor(Parameters<?, ?> parameters, Object[] values, EntityManager em) {
50+
4751
super(parameters, values);
52+
4853
Session session = em.unwrap(Session.class);
4954
this.typeHelper = session.getSessionFactory().getTypeHelper();
5055
}
5156

57+
@Override
5258
public Object getValue(Parameter parameter) {
59+
5360
Object value = super.getValue(parameter.getIndex());
54-
if (value == null) {
55-
Type type = typeHelper.basic(parameter.getType());
56-
if (type == null) {
57-
return null;
58-
}
59-
return new TypedParameterValue(type, null);
61+
if (value != null) {
62+
return value;
6063
}
61-
return value;
62-
}
6364

64-
@Override
65-
public Object[] getValues() {
66-
return super.getValues();
65+
Type type = typeHelper.basic(parameter.getType());
66+
if (type == null) {
67+
return null;
68+
}
69+
return new TypedParameterValue(type, null);
6770
}
6871
}

Diff for: src/main/java/org/springframework/data/jpa/provider/PersistenceProvider.java

+11
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
import org.hibernate.ScrollableResults;
3535
import org.hibernate.proxy.HibernateProxy;
3636

37+
import org.springframework.data.jpa.repository.query.JpaParameters;
38+
import org.springframework.data.jpa.repository.query.JpaParametersParameterAccessor;
3739
import org.springframework.data.util.CloseableIterator;
3840
import org.springframework.lang.Nullable;
3941
import org.springframework.transaction.support.TransactionSynchronizationManager;
@@ -114,6 +116,11 @@ public Object getIdentifierFrom(Object entity) {
114116
public CloseableIterator<Object> executeQueryWithResultStream(Query jpaQuery) {
115117
return new HibernateScrollableResultsIterator(jpaQuery);
116118
}
119+
120+
@Override
121+
public JpaParametersParameterAccessor getParameterAccessor(JpaParameters parameters, Object[] values, EntityManager em) {
122+
return new HibernateJpaParametersParameterAccessor(parameters, values, em);
123+
}
117124
},
118125

119126
/**
@@ -286,6 +293,10 @@ public static PersistenceProvider fromMetamodel(Metamodel metamodel) {
286293
return cacheAndReturn(metamodelType, GENERIC_JPA);
287294
}
288295

296+
public JpaParametersParameterAccessor getParameterAccessor(JpaParameters parameters, Object[] values, EntityManager em) {
297+
return new JpaParametersParameterAccessor(parameters, values);
298+
}
299+
289300
/**
290301
* Returns the placeholder to be used for simple count queries. Default implementation returns {@code x}.
291302
*

Diff for: src/main/java/org/springframework/data/jpa/repository/query/AbstractJpaQuery.java

+2-5
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,8 @@ private Object doExecute(JpaQueryExecution execution, Object[] values) {
160160
}
161161

162162
private JpaParametersParameterAccessor obtainParameterAccessor(Object[] values) {
163-
if (provider == PersistenceProvider.HIBERNATE) {
164-
return new HibernateJpaParametersParameterAccessor(method.getParameters(), values, em);
165-
} else {
166-
return new JpaParametersParameterAccessor(method.getParameters(), values);
167-
}
163+
164+
return provider.getParameterAccessor(method.getParameters(), values, em);
168165
}
169166

170167
protected JpaQueryExecution getExecution() {

Diff for: src/main/java/org/springframework/data/jpa/repository/query/JpaParametersParameterAccessor.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public class JpaParametersParameterAccessor extends ParametersParameterAccessor
3636
* @param parameters must not be {@literal null}.
3737
* @param values must not be {@literal null}.
3838
*/
39-
JpaParametersParameterAccessor(Parameters<?, ?> parameters, Object[] values) {
39+
public JpaParametersParameterAccessor(Parameters<?, ?> parameters, Object[] values) {
4040
super(parameters, values);
4141
}
4242

Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
package org.springframework.data.jpa.repository.query;
22

3-
import static org.assertj.core.api.Assertions.assertThat;
4-
import static org.mockito.ArgumentMatchers.eq;
5-
import static org.mockito.ArgumentMatchers.isNull;
6-
import static org.mockito.Mockito.mock;
7-
import static org.mockito.Mockito.verify;
3+
import static org.assertj.core.api.Assertions.*;
4+
import static org.mockito.ArgumentMatchers.*;
5+
import static org.mockito.Mockito.*;
86

97
import java.lang.reflect.Method;
108

@@ -19,6 +17,7 @@
1917
import org.junit.jupiter.api.extension.ExtendWith;
2018
import org.mockito.ArgumentCaptor;
2119
import org.springframework.data.jpa.domain.sample.User;
20+
import org.springframework.data.jpa.provider.PersistenceProvider;
2221
import org.springframework.test.context.ContextConfiguration;
2322
import org.springframework.test.context.junit.jupiter.SpringExtension;
2423

@@ -31,56 +30,58 @@
3130
@ContextConfiguration("classpath:infrastructure.xml")
3231
class JpaParametersParameterAccessorTests {
3332

34-
@PersistenceContext
35-
private EntityManager em;
36-
private Query query;
37-
38-
@BeforeEach
39-
void setUp() {
40-
query = mock(Query.class);
41-
}
42-
43-
@Test // GH-2370
44-
void createsJpaParametersParameterAccessor() throws Exception {
45-
46-
Method withNativeQuery = SampleRepository.class.getMethod("withNativeQuery", Integer.class);
47-
Object[] values = { null };
48-
JpaParameters parameters = new JpaParameters(withNativeQuery);
49-
JpaParametersParameterAccessor accessor = new JpaParametersParameterAccessor(parameters, values);
50-
51-
bind(parameters, accessor);
52-
53-
verify(query).setParameter(eq(1), isNull());
54-
}
55-
56-
@Test // GH-2370
57-
void createsHibernateParametersParameterAccessor() throws Exception {
58-
59-
Method withNativeQuery = SampleRepository.class.getMethod("withNativeQuery", Integer.class);
60-
Object[] values = { null };
61-
JpaParameters parameters = new JpaParameters(withNativeQuery);
62-
JpaParametersParameterAccessor accessor =
63-
new HibernateJpaParametersParameterAccessor(parameters, values, em);
64-
65-
bind(parameters, accessor);
66-
67-
ArgumentCaptor<TypedParameterValue> captor = ArgumentCaptor.forClass(TypedParameterValue.class);
68-
verify(query).setParameter(eq(1), captor.capture());
69-
TypedParameterValue captorValue = captor.getValue();
70-
assertThat(captorValue.getType()).isEqualTo(StandardBasicTypes.INTEGER);
71-
assertThat(captorValue.getValue()).isNull();
72-
}
73-
74-
private void bind(JpaParameters parameters, JpaParametersParameterAccessor accessor) {
75-
ParameterBinderFactory.createBinder(parameters).bind(QueryParameterSetter.BindableQuery.from(query),
76-
accessor,
77-
QueryParameterSetter.ErrorHandling.LENIENT);
78-
}
79-
80-
interface SampleRepository {
81-
@org.springframework.data.jpa.repository.Query(
82-
value = "select 1 from user where age = :age",
83-
nativeQuery = true)
84-
User withNativeQuery(Integer age);
85-
}
33+
@PersistenceContext private EntityManager em;
34+
private Query query;
35+
36+
@BeforeEach
37+
void setUp() {
38+
query = mock(Query.class);
39+
}
40+
41+
@Test // GH-2370
42+
void createsJpaParametersParameterAccessor() throws Exception {
43+
44+
Method withNativeQuery = SampleRepository.class.getMethod("withNativeQuery", Integer.class);
45+
Object[] values = { null };
46+
JpaParameters parameters = new JpaParameters(withNativeQuery);
47+
JpaParametersParameterAccessor accessor = PersistenceProvider.GENERIC_JPA.getParameterAccessor(parameters, values, em);
48+
49+
bind(parameters, accessor);
50+
51+
verify(query).setParameter(eq(1), isNull());
52+
}
53+
54+
@Test // GH-2370
55+
void createsHibernateParametersParameterAccessor() throws Exception {
56+
57+
Method withNativeQuery = SampleRepository.class.getMethod("withNativeQuery", Integer.class);
58+
Object[] values = { null };
59+
JpaParameters parameters = new JpaParameters(withNativeQuery);
60+
JpaParametersParameterAccessor accessor = PersistenceProvider.HIBERNATE.getParameterAccessor(parameters, values,
61+
em);
62+
63+
bind(parameters, accessor);
64+
65+
ArgumentCaptor<TypedParameterValue> captor = ArgumentCaptor.forClass(TypedParameterValue.class);
66+
verify(query).setParameter(eq(1), captor.capture());
67+
TypedParameterValue captorValue = captor.getValue();
68+
assertThat(captorValue.getType()).isEqualTo(StandardBasicTypes.INTEGER);
69+
assertThat(captorValue.getValue()).isNull();
70+
}
71+
72+
private void bind(JpaParameters parameters, JpaParametersParameterAccessor accessor) {
73+
74+
ParameterBinderFactory.createBinder(parameters)
75+
.bind( //
76+
QueryParameterSetter.BindableQuery.from(query), //
77+
accessor, //
78+
QueryParameterSetter.ErrorHandling.LENIENT //
79+
);
80+
}
81+
82+
interface SampleRepository {
83+
84+
@org.springframework.data.jpa.repository.Query(value = "select 1 from user where age = :age", nativeQuery = true)
85+
User withNativeQuery(Integer age);
86+
}
8687
}

0 commit comments

Comments
 (0)