Browse Source
We now support configurable conversion by introducing CustomConversions and RelationalConverter. CustomConversions is a registry for converters that should be applied on a per-type basis for properties. CustomConversions is typically registered as bean and fed into RelationalMappingContext and the newly introduced RelationalConverter to consider simple types and conversion rules. RelationalConverter with its implementation BasicRelationalConverter encapsulates conversion infrastructure such as EntityInstantiator, CustomConversions, and MappingContext that is required during relational value conversion. BasicRelationalConverter is responsible for simple value conversion and entity instantiation to pull related code together. It's not in full charge of row result to object mapping as this responsibility remains as part of DataAccessStrategy. This change supersedes and removes ConversionCustomizer.pull/79/head
22 changed files with 833 additions and 239 deletions
@ -0,0 +1,59 @@
@@ -0,0 +1,59 @@
|
||||
/* |
||||
* Copyright 2018 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.data.jdbc.core.convert; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcSimpleTypes; |
||||
|
||||
/** |
||||
* Value object to capture custom conversion. {@link JdbcCustomConversions} also act as factory for |
||||
* {@link org.springframework.data.mapping.model.SimpleTypeHolder} |
||||
* |
||||
* @author Mark Paluch |
||||
* @see org.springframework.data.convert.CustomConversions |
||||
* @see org.springframework.data.mapping.model.SimpleTypeHolder |
||||
* @see JdbcSimpleTypes |
||||
*/ |
||||
public class JdbcCustomConversions extends org.springframework.data.convert.CustomConversions { |
||||
|
||||
private static final StoreConversions STORE_CONVERSIONS; |
||||
private static final List<Object> STORE_CONVERTERS; |
||||
|
||||
static { |
||||
|
||||
STORE_CONVERTERS = Collections.emptyList(); |
||||
STORE_CONVERSIONS = StoreConversions.of(JdbcSimpleTypes.HOLDER, STORE_CONVERTERS); |
||||
} |
||||
|
||||
/** |
||||
* Creates an empty {@link JdbcCustomConversions} object. |
||||
*/ |
||||
public JdbcCustomConversions() { |
||||
this(Collections.emptyList()); |
||||
} |
||||
|
||||
/** |
||||
* Create a new {@link JdbcCustomConversions} instance registering the given converters. |
||||
* |
||||
* @param converters must not be {@literal null}. |
||||
*/ |
||||
public JdbcCustomConversions(List<?> converters) { |
||||
super(STORE_CONVERSIONS, converters); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,77 @@
@@ -0,0 +1,77 @@
|
||||
/* |
||||
* Copyright 2018 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.data.jdbc.core.mapping; |
||||
|
||||
import java.math.BigDecimal; |
||||
import java.math.BigInteger; |
||||
import java.sql.Array; |
||||
import java.sql.Blob; |
||||
import java.sql.Clob; |
||||
import java.sql.NClob; |
||||
import java.sql.Ref; |
||||
import java.sql.RowId; |
||||
import java.sql.Struct; |
||||
import java.sql.Time; |
||||
import java.sql.Timestamp; |
||||
import java.util.Collections; |
||||
import java.util.HashSet; |
||||
import java.util.Set; |
||||
import java.util.UUID; |
||||
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder; |
||||
|
||||
/** |
||||
* Simple constant holder for a {@link SimpleTypeHolder} enriched with specific simple types for relational database |
||||
* access. |
||||
* |
||||
* @author Mark Paluch |
||||
*/ |
||||
public abstract class JdbcSimpleTypes { |
||||
|
||||
public static final Set<Class<?>> AUTOGENERATED_ID_TYPES; |
||||
|
||||
static { |
||||
|
||||
Set<Class<?>> classes = new HashSet<>(); |
||||
classes.add(Long.class); |
||||
classes.add(String.class); |
||||
classes.add(BigInteger.class); |
||||
classes.add(BigDecimal.class); |
||||
classes.add(UUID.class); |
||||
AUTOGENERATED_ID_TYPES = Collections.unmodifiableSet(classes); |
||||
|
||||
Set<Class<?>> simpleTypes = new HashSet<>(); |
||||
simpleTypes.add(BigDecimal.class); |
||||
simpleTypes.add(BigInteger.class); |
||||
simpleTypes.add(Array.class); |
||||
simpleTypes.add(Clob.class); |
||||
simpleTypes.add(Blob.class); |
||||
simpleTypes.add(java.sql.Date.class); |
||||
simpleTypes.add(NClob.class); |
||||
simpleTypes.add(Ref.class); |
||||
simpleTypes.add(RowId.class); |
||||
simpleTypes.add(Struct.class); |
||||
simpleTypes.add(Time.class); |
||||
simpleTypes.add(Timestamp.class); |
||||
|
||||
JDBC_SIMPLE_TYPES = Collections.unmodifiableSet(simpleTypes); |
||||
} |
||||
|
||||
private static final Set<Class<?>> JDBC_SIMPLE_TYPES; |
||||
public static final SimpleTypeHolder HOLDER = new SimpleTypeHolder(JDBC_SIMPLE_TYPES, true); |
||||
|
||||
private JdbcSimpleTypes() {} |
||||
} |
||||
@ -0,0 +1,256 @@
@@ -0,0 +1,256 @@
|
||||
/* |
||||
* Copyright 2018 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.data.relational.core.conversion; |
||||
|
||||
import lombok.RequiredArgsConstructor; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.Optional; |
||||
|
||||
import org.springframework.core.convert.ConversionService; |
||||
import org.springframework.core.convert.support.ConfigurableConversionService; |
||||
import org.springframework.core.convert.support.DefaultConversionService; |
||||
import org.springframework.data.convert.CustomConversions; |
||||
import org.springframework.data.convert.CustomConversions.StoreConversions; |
||||
import org.springframework.data.convert.EntityInstantiators; |
||||
import org.springframework.data.mapping.PersistentEntity; |
||||
import org.springframework.data.mapping.PersistentProperty; |
||||
import org.springframework.data.mapping.PersistentPropertyAccessor; |
||||
import org.springframework.data.mapping.PreferredConstructor.Parameter; |
||||
import org.springframework.data.mapping.context.MappingContext; |
||||
import org.springframework.data.mapping.model.ConvertingPropertyAccessor; |
||||
import org.springframework.data.mapping.model.ParameterValueProvider; |
||||
import org.springframework.data.mapping.model.SimpleTypeHolder; |
||||
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity; |
||||
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; |
||||
import org.springframework.data.util.TypeInformation; |
||||
import org.springframework.lang.Nullable; |
||||
import org.springframework.util.Assert; |
||||
import org.springframework.util.ClassUtils; |
||||
|
||||
/** |
||||
* {@link RelationalConverter} that uses a {@link MappingContext} to apply basic conversion of relational values to |
||||
* property values. |
||||
* <p> |
||||
* Conversion is configurable by providing a customized {@link CustomConversions}. |
||||
* |
||||
* @author Mark Paluch |
||||
* @see MappingContext |
||||
* @see SimpleTypeHolder |
||||
* @see CustomConversions |
||||
*/ |
||||
public class BasicRelationalConverter implements RelationalConverter { |
||||
|
||||
private final MappingContext<? extends RelationalPersistentEntity<?>, RelationalPersistentProperty> context; |
||||
private final ConfigurableConversionService conversionService; |
||||
private final EntityInstantiators entityInstantiators; |
||||
private final CustomConversions conversions; |
||||
|
||||
/** |
||||
* Creates a new {@link BasicRelationalConverter} given {@link MappingContext}. |
||||
* |
||||
* @param context must not be {@literal null}. org.springframework.data.jdbc.core.DefaultDataAccessStrategyUnitTests |
||||
*/ |
||||
public BasicRelationalConverter( |
||||
MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> context) { |
||||
this(context, new CustomConversions(StoreConversions.NONE, Collections.emptyList()), new DefaultConversionService(), |
||||
new EntityInstantiators()); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@link BasicRelationalConverter} given {@link MappingContext} and {@link CustomConversions}. |
||||
* |
||||
* @param context must not be {@literal null}. |
||||
* @param conversions must not be {@literal null}. |
||||
*/ |
||||
public BasicRelationalConverter( |
||||
MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> context, |
||||
CustomConversions conversions) { |
||||
this(context, conversions, new DefaultConversionService(), new EntityInstantiators()); |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
private BasicRelationalConverter( |
||||
MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> context, |
||||
CustomConversions conversions, ConfigurableConversionService conversionService, |
||||
EntityInstantiators entityInstantiators) { |
||||
|
||||
Assert.notNull(context, "MappingContext must not be null!"); |
||||
Assert.notNull(conversions, "CustomConversions must not be null!"); |
||||
|
||||
this.context = (MappingContext) context; |
||||
this.conversionService = conversionService; |
||||
this.entityInstantiators = entityInstantiators; |
||||
this.conversions = conversions; |
||||
|
||||
conversions.registerConvertersIn(this.conversionService); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see org.springframework.data.relational.core.conversion.RelationalConverter#getConversionService() |
||||
*/ |
||||
@Override |
||||
public ConversionService getConversionService() { |
||||
return conversionService; |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see org.springframework.data.relational.core.conversion.RelationalConverter#getMappingContext() |
||||
*/ |
||||
@Override |
||||
public MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> getMappingContext() { |
||||
return context; |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see org.springframework.data.relational.core.conversion.RelationalConverter#getPropertyAccessor(org.springframework.data.mapping.PersistentEntity, java.lang.Object) |
||||
*/ |
||||
@Override |
||||
public <T> PersistentPropertyAccessor<T> getPropertyAccessor(PersistentEntity<T, ?> persistentEntity, T instance) { |
||||
|
||||
PersistentPropertyAccessor<T> accessor = persistentEntity.getPropertyAccessor(instance); |
||||
return new ConvertingPropertyAccessor<>(accessor, conversionService); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see org.springframework.data.relational.core.conversion.RelationalConverter#createInstance(org.springframework.data.mapping.PersistentEntity, org.springframework.data.mapping.model.ParameterValueProvider) |
||||
*/ |
||||
@Override |
||||
public <T> T createInstance(PersistentEntity<T, RelationalPersistentProperty> entity, |
||||
ParameterValueProvider<RelationalPersistentProperty> parameterValueProvider) { |
||||
|
||||
return entityInstantiators.getInstantiatorFor(entity) //
|
||||
.createInstance(entity, new ConvertingParameterValueProvider<>(parameterValueProvider)); |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see org.springframework.data.relational.core.conversion.RelationalConverter#readValue(java.lang.Object, org.springframework.data.util.TypeInformation) |
||||
*/ |
||||
@Override |
||||
@Nullable |
||||
public Object readValue(@Nullable Object value, TypeInformation<?> type) { |
||||
|
||||
if (null == value) { |
||||
return null; |
||||
} |
||||
|
||||
if (conversions.hasCustomReadTarget(value.getClass(), type.getType())) { |
||||
return conversionService.convert(value, type.getType()); |
||||
} else { |
||||
return getPotentiallyConvertedSimpleRead(value, type.getType()); |
||||
} |
||||
} |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see org.springframework.data.relational.core.conversion.RelationalConverter#writeValue(java.lang.Object, org.springframework.data.util.TypeInformation) |
||||
*/ |
||||
@Override |
||||
@Nullable |
||||
public Object writeValue(@Nullable Object value, TypeInformation<?> type) { |
||||
|
||||
if (value == null) { |
||||
return null; |
||||
} |
||||
|
||||
Class<?> rawType = type.getType(); |
||||
RelationalPersistentEntity<?> persistentEntity = context.getPersistentEntity(value.getClass()); |
||||
|
||||
if (persistentEntity != null) { |
||||
|
||||
Object id = persistentEntity.getIdentifierAccessor(value).getIdentifier(); |
||||
return writeValue(id, type); |
||||
} |
||||
|
||||
if (rawType.isInstance(value)) { |
||||
return getPotentiallyConvertedSimpleWrite(value); |
||||
} |
||||
|
||||
return conversionService.convert(value, rawType); |
||||
} |
||||
|
||||
/** |
||||
* Checks whether we have a custom conversion registered for the given value into an arbitrary simple JDBC type. |
||||
* Returns the converted value if so. If not, we perform special enum handling or simply return the value as is. |
||||
* |
||||
* @param value |
||||
* @return |
||||
*/ |
||||
private Object getPotentiallyConvertedSimpleWrite(Object value) { |
||||
|
||||
Optional<Class<?>> customTarget = conversions.getCustomWriteTarget(value.getClass()); |
||||
|
||||
if (customTarget.isPresent()) { |
||||
return conversionService.convert(value, customTarget.get()); |
||||
} |
||||
|
||||
return Enum.class.isAssignableFrom(value.getClass()) ? ((Enum<?>) value).name() : value; |
||||
} |
||||
|
||||
/** |
||||
* Checks whether we have a custom conversion for the given simple object. Converts the given value if so, applies |
||||
* {@link Enum} handling or returns the value as is. |
||||
* |
||||
* @param value |
||||
* @param target must not be {@literal null}. |
||||
* @return |
||||
*/ |
||||
@Nullable |
||||
@SuppressWarnings({ "rawtypes", "unchecked" }) |
||||
private Object getPotentiallyConvertedSimpleRead(@Nullable Object value, @Nullable Class<?> target) { |
||||
|
||||
if (value == null || target == null || ClassUtils.isAssignableValue(target, value)) { |
||||
return value; |
||||
} |
||||
|
||||
if (conversions.hasCustomReadTarget(value.getClass(), target)) { |
||||
return conversionService.convert(value, target); |
||||
} |
||||
|
||||
if (Enum.class.isAssignableFrom(target)) { |
||||
return Enum.valueOf((Class<Enum>) target, value.toString()); |
||||
} |
||||
|
||||
return conversionService.convert(value, target); |
||||
} |
||||
|
||||
/** |
||||
* Converter-aware {@link ParameterValueProvider}. |
||||
* |
||||
* @param <P> |
||||
* @author Mark Paluch |
||||
*/ |
||||
@RequiredArgsConstructor |
||||
class ConvertingParameterValueProvider<P extends PersistentProperty<P>> implements ParameterValueProvider<P> { |
||||
|
||||
private final ParameterValueProvider<P> delegate; |
||||
|
||||
/* |
||||
* (non-Javadoc) |
||||
* @see org.springframework.data.mapping.model.ParameterValueProvider#getParameterValue(org.springframework.data.mapping.PreferredConstructor.Parameter) |
||||
*/ |
||||
@Override |
||||
@SuppressWarnings("unchecked") |
||||
public <T> T getParameterValue(Parameter<T, P> parameter) { |
||||
return (T) readValue(delegate.getParameterValue(parameter), parameter.getType()); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,90 @@
@@ -0,0 +1,90 @@
|
||||
/* |
||||
* Copyright 2018 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.data.relational.core.conversion; |
||||
|
||||
import org.springframework.core.convert.ConversionService; |
||||
import org.springframework.data.mapping.PersistentEntity; |
||||
import org.springframework.data.mapping.PersistentPropertyAccessor; |
||||
import org.springframework.data.mapping.context.MappingContext; |
||||
import org.springframework.data.mapping.model.ParameterValueProvider; |
||||
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity; |
||||
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; |
||||
import org.springframework.data.util.TypeInformation; |
||||
import org.springframework.lang.Nullable; |
||||
|
||||
/** |
||||
* A {@link RelationalConverter} is responsible for converting for values to the native relational representation and |
||||
* vice versa. |
||||
* |
||||
* @author Mark Paluch |
||||
*/ |
||||
public interface RelationalConverter { |
||||
|
||||
/** |
||||
* Returns the underlying {@link MappingContext} used by the converter. |
||||
* |
||||
* @return never {@literal null} |
||||
*/ |
||||
MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> getMappingContext(); |
||||
|
||||
/** |
||||
* Returns the underlying {@link ConversionService} used by the converter. |
||||
* |
||||
* @return never {@literal null}. |
||||
*/ |
||||
ConversionService getConversionService(); |
||||
|
||||
/** |
||||
* Create a new instance of {@link PersistentEntity} given {@link ParameterValueProvider} to obtain constructor |
||||
* properties. |
||||
* |
||||
* @param entity |
||||
* @param parameterValueProvider |
||||
* @param <T> |
||||
* @return |
||||
*/ |
||||
<T> T createInstance(PersistentEntity<T, RelationalPersistentProperty> entity, |
||||
ParameterValueProvider<RelationalPersistentProperty> parameterValueProvider); |
||||
|
||||
/** |
||||
* Return a {@link PersistentPropertyAccessor} to access property values of the {@code instance}. |
||||
* |
||||
* @param persistentEntity |
||||
* @param instance |
||||
* @return |
||||
*/ |
||||
<T> PersistentPropertyAccessor<T> getPropertyAccessor(PersistentEntity<T, ?> persistentEntity, T instance); |
||||
|
||||
/** |
||||
* Read a relational value into the desired {@link TypeInformation destination type}. |
||||
* |
||||
* @param value |
||||
* @param type |
||||
* @return |
||||
*/ |
||||
@Nullable |
||||
Object readValue(@Nullable Object value, TypeInformation<?> type); |
||||
|
||||
/** |
||||
* Write a property value into a relational type that can be stored natively. |
||||
* |
||||
* @param value |
||||
* @param type |
||||
* @return |
||||
*/ |
||||
@Nullable |
||||
Object writeValue(@Nullable Object value, TypeInformation<?> type); |
||||
} |
||||
@ -1,40 +0,0 @@
@@ -1,40 +0,0 @@
|
||||
/* |
||||
* Copyright 2017-2018 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.data.relational.core.mapping; |
||||
|
||||
import org.springframework.core.convert.support.GenericConversionService; |
||||
|
||||
/** |
||||
* Interface to register custom conversions. |
||||
* |
||||
* @author Jens Schauder |
||||
* @since 1.0 |
||||
*/ |
||||
public interface ConversionCustomizer { |
||||
|
||||
/** |
||||
* Noop instance to be used as a default. |
||||
*/ |
||||
ConversionCustomizer NONE = __ -> {}; |
||||
|
||||
/** |
||||
* Gets called in order to allow the customization of the {@link org.springframework.core.convert.ConversionService}. |
||||
* Typically used by registering additional conversions. |
||||
* |
||||
* @param conversions the conversions that get customized. |
||||
*/ |
||||
void customize(GenericConversionService conversions); |
||||
} |
||||
@ -0,0 +1,104 @@
@@ -0,0 +1,104 @@
|
||||
/* |
||||
* Copyright 2018 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.data.relational.core.conversion; |
||||
|
||||
import static org.assertj.core.api.Assertions.*; |
||||
|
||||
import lombok.Data; |
||||
import lombok.Value; |
||||
|
||||
import org.junit.Test; |
||||
import org.springframework.data.mapping.PersistentPropertyAccessor; |
||||
import org.springframework.data.mapping.PreferredConstructor.Parameter; |
||||
import org.springframework.data.mapping.model.ParameterValueProvider; |
||||
import org.springframework.data.relational.core.mapping.RelationalMappingContext; |
||||
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity; |
||||
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; |
||||
import org.springframework.data.util.ClassTypeInformation; |
||||
|
||||
/** |
||||
* Unit tests for {@link BasicRelationalConverter}. |
||||
* |
||||
* @author Mark Paluch |
||||
*/ |
||||
public class BasicRelationalConverterUnitTests { |
||||
|
||||
RelationalMappingContext context = new RelationalMappingContext(); |
||||
RelationalConverter converter = new BasicRelationalConverter(context); |
||||
|
||||
@Test // DATAJDBC-235
|
||||
@SuppressWarnings("unchecked") |
||||
public void shouldUseConvertingPropertyAccessor() { |
||||
|
||||
RelationalPersistentEntity<MyEntity> entity = (RelationalPersistentEntity) context |
||||
.getRequiredPersistentEntity(MyEntity.class); |
||||
|
||||
MyEntity instance = new MyEntity(); |
||||
|
||||
PersistentPropertyAccessor<MyEntity> accessor = converter.getPropertyAccessor(entity, instance); |
||||
RelationalPersistentProperty property = entity.getRequiredPersistentProperty("flag"); |
||||
accessor.setProperty(property, "1"); |
||||
|
||||
assertThat(instance.isFlag()).isTrue(); |
||||
} |
||||
|
||||
@Test // DATAJDBC-235
|
||||
public void shouldConvertEnumToString() { |
||||
|
||||
Object result = converter.writeValue(MyEnum.ON, ClassTypeInformation.from(String.class)); |
||||
|
||||
assertThat(result).isEqualTo("ON"); |
||||
} |
||||
|
||||
@Test // DATAJDBC-235
|
||||
public void shouldConvertStringToEnum() { |
||||
|
||||
Object result = converter.readValue("OFF", ClassTypeInformation.from(MyEnum.class)); |
||||
|
||||
assertThat(result).isEqualTo(MyEnum.OFF); |
||||
} |
||||
|
||||
@Test // DATAJDBC-235
|
||||
@SuppressWarnings("unchecked") |
||||
public void shouldCreateInstance() { |
||||
|
||||
RelationalPersistentEntity<MyValue> entity = (RelationalPersistentEntity) context |
||||
.getRequiredPersistentEntity(MyValue.class); |
||||
|
||||
MyValue result = converter.createInstance(entity, new ParameterValueProvider<RelationalPersistentProperty>() { |
||||
@Override |
||||
public <T> T getParameterValue(Parameter<T, RelationalPersistentProperty> parameter) { |
||||
return (T) "bar"; |
||||
} |
||||
}); |
||||
|
||||
assertThat(result.getFoo()).isEqualTo("bar"); |
||||
} |
||||
|
||||
@Data |
||||
static class MyEntity { |
||||
boolean flag; |
||||
} |
||||
|
||||
@Value |
||||
static class MyValue { |
||||
final String foo; |
||||
} |
||||
|
||||
enum MyEnum { |
||||
ON, OFF; |
||||
} |
||||
} |
||||
Loading…
Reference in new issue