1616package org .springframework .data .mapping .model ;
1717
1818import static org .assertj .core .api .Assertions .*;
19+ import static org .mockito .ArgumentMatchers .*;
1920import static org .mockito .Mockito .*;
2021
2122import lombok .AllArgsConstructor ;
2223import lombok .Data ;
2324import lombok .Value ;
2425
25- import org . junit . jupiter . api . Test ;
26+ import java . util . stream . Stream ;
2627
28+ import org .junit .jupiter .api .DynamicTest ;
29+ import org .junit .jupiter .api .Named ;
30+ import org .junit .jupiter .api .Test ;
31+ import org .junit .jupiter .api .TestFactory ;
2732import org .springframework .core .convert .ConversionService ;
2833import org .springframework .core .convert .support .DefaultConversionService ;
34+ import org .springframework .data .mapping .PersistentEntity ;
35+ import org .springframework .data .mapping .PersistentProperty ;
2936import org .springframework .data .mapping .PersistentPropertyAccessor ;
3037import org .springframework .data .mapping .context .SampleMappingContext ;
3138import org .springframework .data .mapping .context .SamplePersistentProperty ;
@@ -122,17 +129,47 @@ public void shouldConvertToPropertyPathLeafType() {
122129 var context = new SampleMappingContext ();
123130
124131 var accessor = context .getPersistentEntity (Order .class ).getPropertyAccessor (order );
125- var convertingAccessor = new ConvertingPropertyAccessor <Order >(accessor ,
126- new DefaultConversionService ());
132+ var convertingAccessor = new ConvertingPropertyAccessor <Order >(accessor , new DefaultConversionService ());
127133
128- var path = context .getPersistentPropertyPath ("customer.firstname" ,
129- Order .class );
134+ var path = context .getPersistentPropertyPath ("customer.firstname" , Order .class );
130135
131136 convertingAccessor .setProperty (path , 2 );
132137
133138 assertThat (convertingAccessor .getBean ().getCustomer ().getFirstname ()).isEqualTo ("2" );
134139 }
135140
141+ @ TestFactory // #2546
142+ Stream <DynamicTest > doesNotInvokeConversionForMatchingPrimitives () {
143+
144+ IntegerWrapper wrapper = new IntegerWrapper ();
145+ wrapper .primitive = 42 ;
146+ wrapper .boxed = 42 ;
147+
148+ SampleMappingContext context = new SampleMappingContext ();
149+ PersistentEntity <Object , SamplePersistentProperty > entity = context
150+ .getRequiredPersistentEntity (IntegerWrapper .class );
151+
152+ SamplePersistentProperty primitiveProperty = entity .getRequiredPersistentProperty ("primitive" );
153+ SamplePersistentProperty boxedProperty = entity .getRequiredPersistentProperty ("boxed" );
154+
155+ PersistentPropertyAccessor <IntegerWrapper > accessor = entity .getPropertyAccessor (wrapper );
156+ ConversionService conversionService = mock (ConversionService .class );
157+
158+ ConvertingPropertyAccessor <IntegerWrapper > convertingAccessor = new ConvertingPropertyAccessor <>(accessor ,
159+ conversionService );
160+
161+ Stream <PrimitiveFixture > fixtures = Stream .of (PrimitiveFixture .$ (boxedProperty , int .class ),
162+ PrimitiveFixture .$ (boxedProperty , Integer .class ), PrimitiveFixture .$ (primitiveProperty , int .class ),
163+ PrimitiveFixture .$ (primitiveProperty , Integer .class ));
164+
165+ return DynamicTest .stream (fixtures , it -> {
166+
167+ convertingAccessor .getProperty (it .property , it .type );
168+
169+ verify (conversionService , never ()).convert (any (), eq (it .type ));
170+ });
171+ }
172+
136173 private static ConvertingPropertyAccessor getAccessor (Object entity , ConversionService conversionService ) {
137174
138175 PersistentPropertyAccessor wrapper = new BeanWrapper <>(entity );
@@ -142,8 +179,7 @@ private static ConvertingPropertyAccessor getAccessor(Object entity, ConversionS
142179 private static SamplePersistentProperty getIdProperty () {
143180
144181 var mappingContext = new SampleMappingContext ();
145- var entity = mappingContext
146- .getRequiredPersistentEntity (Entity .class );
182+ var entity = mappingContext .getRequiredPersistentEntity (Entity .class );
147183 return entity .getPersistentProperty ("id" );
148184 }
149185
@@ -161,4 +197,26 @@ static class Order {
161197 static class Customer {
162198 String firstname ;
163199 }
200+
201+ static class IntegerWrapper {
202+ int primitive ;
203+ Integer boxed ;
204+ }
205+
206+ @ Value (staticConstructor = "$" )
207+ static class PrimitiveFixture implements Named <PrimitiveFixture > {
208+
209+ PersistentProperty <?> property ;
210+ Class <?> type ;
211+
212+ @ Override
213+ public String getName () {
214+ return String .format ("Accessing %s as %s does not cause conversion." , property , type );
215+ }
216+
217+ @ Override
218+ public PrimitiveFixture getPayload () {
219+ return this ;
220+ }
221+ }
164222}
0 commit comments