38 changed files with 11 additions and 1589 deletions
@ -1,77 +0,0 @@
@@ -1,77 +0,0 @@
|
||||
/* |
||||
* Copyright 2023-2024 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 |
||||
* |
||||
* https://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 org.springframework.data.convert.CustomConversions; |
||||
import org.springframework.data.mapping.context.MappingContext; |
||||
import org.springframework.data.relational.core.conversion.RelationalConverter; |
||||
import org.springframework.data.relational.core.mapping.RelationalMappingContext; |
||||
import org.springframework.data.relational.core.sql.IdentifierProcessing; |
||||
|
||||
/** |
||||
* {@link RelationalConverter} that uses a {@link MappingContext} to apply conversion of relational values to property |
||||
* values. |
||||
* <p> |
||||
* Conversion is configurable by providing a customized {@link CustomConversions}. |
||||
* |
||||
* @author Mark Paluch |
||||
* @since 1.1 |
||||
* @deprecated since 3.2, use {@link MappingJdbcConverter} instead as the naming suggests a limited scope of |
||||
* functionality. |
||||
*/ |
||||
@Deprecated(since = "3.2") |
||||
public class BasicJdbcConverter extends MappingJdbcConverter { |
||||
|
||||
/** |
||||
* Creates a new {@link BasicJdbcConverter} given {@link MappingContext} and a {@link JdbcTypeFactory#unsupported() |
||||
* no-op type factory} throwing {@link UnsupportedOperationException} on type creation. Use |
||||
* {@link #BasicJdbcConverter(RelationalMappingContext, RelationResolver, CustomConversions, JdbcTypeFactory, IdentifierProcessing)} |
||||
* (MappingContext, RelationResolver, JdbcTypeFactory)} to convert arrays and large objects into JDBC-specific types. |
||||
* |
||||
* @param context must not be {@literal null}. |
||||
* @param relationResolver used to fetch additional relations from the database. Must not be {@literal null}. |
||||
*/ |
||||
public BasicJdbcConverter(RelationalMappingContext context, RelationResolver relationResolver) { |
||||
super(context, relationResolver); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@link BasicJdbcConverter} given {@link MappingContext}. |
||||
* |
||||
* @param context must not be {@literal null}. |
||||
* @param relationResolver used to fetch additional relations from the database. Must not be {@literal null}. |
||||
* @param typeFactory must not be {@literal null} |
||||
* @since 3.2 |
||||
*/ |
||||
public BasicJdbcConverter(RelationalMappingContext context, RelationResolver relationResolver, |
||||
CustomConversions conversions, JdbcTypeFactory typeFactory) { |
||||
super(context, relationResolver, conversions, typeFactory); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new {@link BasicJdbcConverter} given {@link MappingContext}. |
||||
* |
||||
* @param context must not be {@literal null}. |
||||
* @param relationResolver used to fetch additional relations from the database. Must not be {@literal null}. |
||||
* @param typeFactory must not be {@literal null} |
||||
* @param identifierProcessing must not be {@literal null} |
||||
* @since 2.0 |
||||
*/ |
||||
public BasicJdbcConverter(RelationalMappingContext context, RelationResolver relationResolver, |
||||
CustomConversions conversions, JdbcTypeFactory typeFactory, IdentifierProcessing identifierProcessing) { |
||||
super(context, relationResolver, conversions, typeFactory); |
||||
} |
||||
} |
||||
@ -1,79 +0,0 @@
@@ -1,79 +0,0 @@
|
||||
/* |
||||
* Copyright 2022-2024 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 |
||||
* |
||||
* https://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 org.springframework.jdbc.core.JdbcOperations; |
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; |
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; |
||||
import org.springframework.jdbc.core.namedparam.SqlParameterSource; |
||||
import org.springframework.jdbc.support.KeyHolder; |
||||
import org.springframework.lang.Nullable; |
||||
|
||||
/** |
||||
* Counterpart to {@link org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations} containing methods for |
||||
* performing batch updates with generated keys. |
||||
* |
||||
* @author Chirag Tailor |
||||
* @author Mark Paluch |
||||
* @since 2.4 |
||||
* @deprecated since 3.2. Use {@link org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations#batchUpdate} |
||||
* methods instead. |
||||
*/ |
||||
@Deprecated(since = "3.2") |
||||
public class BatchJdbcOperations { |
||||
|
||||
private final NamedParameterJdbcOperations jdbcOperations; |
||||
|
||||
public BatchJdbcOperations(JdbcOperations jdbcOperations) { |
||||
this.jdbcOperations = new NamedParameterJdbcTemplate(jdbcOperations); |
||||
} |
||||
|
||||
/** |
||||
* Execute a batch using the supplied SQL statement with the batch of supplied arguments, returning generated keys. |
||||
* |
||||
* @param sql the SQL statement to execute |
||||
* @param batchArgs the array of {@link SqlParameterSource} containing the batch of arguments for the query |
||||
* @param generatedKeyHolder a {@link KeyHolder} that will hold the generated keys |
||||
* @return an array containing the numbers of rows affected by each update in the batch (may also contain special |
||||
* JDBC-defined negative values for affected rows such as |
||||
* {@link java.sql.Statement#SUCCESS_NO_INFO}/{@link java.sql.Statement#EXECUTE_FAILED}) |
||||
* @throws org.springframework.dao.DataAccessException if there is any problem issuing the update |
||||
* @see org.springframework.jdbc.support.GeneratedKeyHolder |
||||
* @since 2.4 |
||||
*/ |
||||
int[] batchUpdate(String sql, SqlParameterSource[] batchArgs, KeyHolder generatedKeyHolder) { |
||||
return jdbcOperations.batchUpdate(sql, batchArgs, generatedKeyHolder); |
||||
} |
||||
|
||||
/** |
||||
* Execute a batch using the supplied SQL statement with the batch of supplied arguments, returning generated keys. |
||||
* |
||||
* @param sql the SQL statement to execute |
||||
* @param batchArgs the array of {@link SqlParameterSource} containing the batch of arguments for the query |
||||
* @param generatedKeyHolder a {@link KeyHolder} that will hold the generated keys |
||||
* @param keyColumnNames names of the columns that will have keys generated for them |
||||
* @return an array containing the numbers of rows affected by each update in the batch (may also contain special |
||||
* JDBC-defined negative values for affected rows such as |
||||
* {@link java.sql.Statement#SUCCESS_NO_INFO}/{@link java.sql.Statement#EXECUTE_FAILED}) |
||||
* @throws org.springframework.dao.DataAccessException if there is any problem issuing the update |
||||
* @see org.springframework.jdbc.support.GeneratedKeyHolder |
||||
* @since 2.4 |
||||
*/ |
||||
int[] batchUpdate(String sql, SqlParameterSource[] batchArgs, KeyHolder generatedKeyHolder, |
||||
@Nullable String[] keyColumnNames) { |
||||
return jdbcOperations.batchUpdate(sql, batchArgs, generatedKeyHolder, keyColumnNames); |
||||
} |
||||
} |
||||
@ -1,290 +0,0 @@
@@ -1,290 +0,0 @@
|
||||
/* |
||||
* Copyright 2019-2024 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 |
||||
* |
||||
* https://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; |
||||
|
||||
import static org.assertj.core.api.Assertions.*; |
||||
import static org.assertj.core.api.SoftAssertions.*; |
||||
import static org.springframework.data.relational.core.sql.SqlIdentifier.*; |
||||
|
||||
import java.util.List; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
import org.springframework.data.annotation.Id; |
||||
import org.springframework.data.annotation.ReadOnlyProperty; |
||||
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext; |
||||
import org.springframework.data.mapping.PersistentPropertyPath; |
||||
import org.springframework.data.relational.core.mapping.Embedded; |
||||
import org.springframework.data.relational.core.mapping.Embedded.OnEmpty; |
||||
import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension; |
||||
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity; |
||||
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; |
||||
|
||||
/** |
||||
* @author Jens Schauder |
||||
* @author Daniil Razorenov |
||||
*/ |
||||
public class PersistentPropertyPathExtensionUnitTests { |
||||
|
||||
JdbcMappingContext context = new JdbcMappingContext(); |
||||
private RelationalPersistentEntity<?> entity = context.getRequiredPersistentEntity(DummyEntity.class); |
||||
|
||||
@Test // DATAJDBC-340
|
||||
void isEmbedded() { |
||||
|
||||
assertSoftly(softly -> { |
||||
|
||||
softly.assertThat(extPath(entity).isEmbedded()).isFalse(); |
||||
softly.assertThat(extPath("second").isEmbedded()).isFalse(); |
||||
softly.assertThat(extPath("second.third2").isEmbedded()).isTrue(); |
||||
}); |
||||
} |
||||
|
||||
@Test // DATAJDBC-340
|
||||
void isMultiValued() { |
||||
|
||||
assertSoftly(softly -> { |
||||
|
||||
softly.assertThat(extPath(entity).isMultiValued()).isFalse(); |
||||
softly.assertThat(extPath("second").isMultiValued()).isFalse(); |
||||
softly.assertThat(extPath("second.third2").isMultiValued()).isFalse(); |
||||
softly.assertThat(extPath("secondList.third2").isMultiValued()).isTrue(); |
||||
softly.assertThat(extPath("secondList").isMultiValued()).isTrue(); |
||||
}); |
||||
} |
||||
|
||||
@Test // DATAJDBC-340
|
||||
void leafEntity() { |
||||
|
||||
RelationalPersistentEntity<?> second = context.getRequiredPersistentEntity(Second.class); |
||||
RelationalPersistentEntity<?> third = context.getRequiredPersistentEntity(Third.class); |
||||
|
||||
assertSoftly(softly -> { |
||||
|
||||
softly.assertThat(extPath(entity).getLeafEntity()).isEqualTo(entity); |
||||
softly.assertThat(extPath("second").getLeafEntity()).isEqualTo(second); |
||||
softly.assertThat(extPath("second.third2").getLeafEntity()).isEqualTo(third); |
||||
softly.assertThat(extPath("secondList.third2").getLeafEntity()).isEqualTo(third); |
||||
softly.assertThat(extPath("secondList").getLeafEntity()).isEqualTo(second); |
||||
}); |
||||
} |
||||
|
||||
@Test // DATAJDBC-340
|
||||
void isEntity() { |
||||
|
||||
assertSoftly(softly -> { |
||||
|
||||
softly.assertThat(extPath(entity).isEntity()).isTrue(); |
||||
String path = "second"; |
||||
softly.assertThat(extPath(path).isEntity()).isTrue(); |
||||
softly.assertThat(extPath("second.third2").isEntity()).isTrue(); |
||||
softly.assertThat(extPath("second.third2.value").isEntity()).isFalse(); |
||||
softly.assertThat(extPath("secondList.third2").isEntity()).isTrue(); |
||||
softly.assertThat(extPath("secondList.third2.value").isEntity()).isFalse(); |
||||
softly.assertThat(extPath("secondList").isEntity()).isTrue(); |
||||
}); |
||||
} |
||||
|
||||
@Test // DATAJDBC-340
|
||||
void getTableName() { |
||||
|
||||
assertSoftly(softly -> { |
||||
|
||||
softly.assertThat(extPath(entity).getQualifiedTableName()).isEqualTo(quoted("DUMMY_ENTITY")); |
||||
softly.assertThat(extPath("second").getQualifiedTableName()).isEqualTo(quoted("SECOND")); |
||||
softly.assertThat(extPath("second.third2").getQualifiedTableName()).isEqualTo(quoted("SECOND")); |
||||
softly.assertThat(extPath("second.third2.value").getQualifiedTableName()).isEqualTo(quoted("SECOND")); |
||||
softly.assertThat(extPath("secondList.third2").getQualifiedTableName()).isEqualTo(quoted("SECOND")); |
||||
softly.assertThat(extPath("secondList.third2.value").getQualifiedTableName()).isEqualTo(quoted("SECOND")); |
||||
softly.assertThat(extPath("secondList").getQualifiedTableName()).isEqualTo(quoted("SECOND")); |
||||
}); |
||||
} |
||||
|
||||
@Test // DATAJDBC-340
|
||||
void getTableAlias() { |
||||
|
||||
assertSoftly(softly -> { |
||||
|
||||
softly.assertThat(extPath(entity).getTableAlias()).isEqualTo(null); |
||||
softly.assertThat(extPath("second").getTableAlias()).isEqualTo(quoted("second")); |
||||
softly.assertThat(extPath("second.third2").getTableAlias()).isEqualTo(quoted("second")); |
||||
softly.assertThat(extPath("second.third2.value").getTableAlias()).isEqualTo(quoted("second")); |
||||
softly.assertThat(extPath("second.third").getTableAlias()).isEqualTo(quoted("second_third")); |
||||
softly.assertThat(extPath("second.third.value").getTableAlias()).isEqualTo(quoted("second_third")); |
||||
softly.assertThat(extPath("secondList.third2").getTableAlias()).isEqualTo(quoted("secondList")); |
||||
softly.assertThat(extPath("secondList.third2.value").getTableAlias()).isEqualTo(quoted("secondList")); |
||||
softly.assertThat(extPath("secondList.third").getTableAlias()).isEqualTo(quoted("secondList_third")); |
||||
softly.assertThat(extPath("secondList.third.value").getTableAlias()).isEqualTo(quoted("secondList_third")); |
||||
softly.assertThat(extPath("secondList").getTableAlias()).isEqualTo(quoted("secondList")); |
||||
softly.assertThat(extPath("second2.third").getTableAlias()).isEqualTo(quoted("secthird")); |
||||
softly.assertThat(extPath("second3.third").getTableAlias()).isEqualTo(quoted("third")); |
||||
}); |
||||
} |
||||
|
||||
@Test // DATAJDBC-340
|
||||
void getColumnName() { |
||||
|
||||
assertSoftly(softly -> { |
||||
|
||||
softly.assertThat(extPath("second.third2.value").getColumnName()).isEqualTo(quoted("THRDVALUE")); |
||||
softly.assertThat(extPath("second.third.value").getColumnName()).isEqualTo(quoted("VALUE")); |
||||
softly.assertThat(extPath("secondList.third2.value").getColumnName()).isEqualTo(quoted("THRDVALUE")); |
||||
softly.assertThat(extPath("secondList.third.value").getColumnName()).isEqualTo(quoted("VALUE")); |
||||
softly.assertThat(extPath("second2.third2.value").getColumnName()).isEqualTo(quoted("SECTHRDVALUE")); |
||||
softly.assertThat(extPath("second2.third.value").getColumnName()).isEqualTo(quoted("VALUE")); |
||||
}); |
||||
} |
||||
|
||||
@Test // DATAJDBC-359
|
||||
void idDefiningPath() { |
||||
|
||||
assertSoftly(softly -> { |
||||
|
||||
softly.assertThat(extPath("second.third2.value").getIdDefiningParentPath().getLength()).isEqualTo(0); |
||||
softly.assertThat(extPath("second.third.value").getIdDefiningParentPath().getLength()).isEqualTo(0); |
||||
softly.assertThat(extPath("secondList.third2.value").getIdDefiningParentPath().getLength()).isEqualTo(0); |
||||
softly.assertThat(extPath("secondList.third.value").getIdDefiningParentPath().getLength()).isEqualTo(0); |
||||
softly.assertThat(extPath("second2.third2.value").getIdDefiningParentPath().getLength()).isEqualTo(0); |
||||
softly.assertThat(extPath("second2.third.value").getIdDefiningParentPath().getLength()).isEqualTo(0); |
||||
softly.assertThat(extPath("withId.second.third2.value").getIdDefiningParentPath().getLength()).isEqualTo(1); |
||||
softly.assertThat(extPath("withId.second.third.value").getIdDefiningParentPath().getLength()).isEqualTo(1); |
||||
}); |
||||
} |
||||
|
||||
@Test // DATAJDBC-359
|
||||
void reverseColumnName() { |
||||
|
||||
assertSoftly(softly -> { |
||||
|
||||
softly.assertThat(extPath("second.third2").getReverseColumnName()).isEqualTo(quoted("DUMMY_ENTITY")); |
||||
softly.assertThat(extPath("second.third").getReverseColumnName()).isEqualTo(quoted("DUMMY_ENTITY")); |
||||
softly.assertThat(extPath("secondList.third2").getReverseColumnName()).isEqualTo(quoted("DUMMY_ENTITY")); |
||||
softly.assertThat(extPath("secondList.third").getReverseColumnName()).isEqualTo(quoted("DUMMY_ENTITY")); |
||||
softly.assertThat(extPath("second2.third2").getReverseColumnName()).isEqualTo(quoted("DUMMY_ENTITY")); |
||||
softly.assertThat(extPath("second2.third").getReverseColumnName()).isEqualTo(quoted("DUMMY_ENTITY")); |
||||
softly.assertThat(extPath("withId.second.third2.value").getReverseColumnName()).isEqualTo(quoted("WITH_ID")); |
||||
softly.assertThat(extPath("withId.second.third").getReverseColumnName()).isEqualTo(quoted("WITH_ID")); |
||||
softly.assertThat(extPath("withId.second2.third").getReverseColumnName()).isEqualTo(quoted("WITH_ID")); |
||||
}); |
||||
} |
||||
|
||||
@Test // DATAJDBC-359
|
||||
void getRequiredIdProperty() { |
||||
|
||||
assertSoftly(softly -> { |
||||
|
||||
softly.assertThat(extPath(entity).getRequiredIdProperty().getName()).isEqualTo("entityId"); |
||||
softly.assertThat(extPath("withId").getRequiredIdProperty().getName()).isEqualTo("withIdId"); |
||||
softly.assertThatThrownBy(() -> extPath("second").getRequiredIdProperty()) |
||||
.isInstanceOf(IllegalStateException.class); |
||||
}); |
||||
} |
||||
|
||||
@Test // DATAJDBC-359
|
||||
void extendBy() { |
||||
|
||||
assertSoftly(softly -> { |
||||
|
||||
softly.assertThat(extPath(entity).extendBy(entity.getRequiredPersistentProperty("withId"))) |
||||
.isEqualTo(extPath("withId")); |
||||
softly.assertThat(extPath("withId").extendBy(extPath("withId").getRequiredIdProperty())) |
||||
.isEqualTo(extPath("withId.withIdId")); |
||||
}); |
||||
} |
||||
|
||||
@Test // GH-1164
|
||||
void equalsWorks() { |
||||
|
||||
PersistentPropertyPathExtension root1 = extPath(entity); |
||||
PersistentPropertyPathExtension root2 = extPath(entity); |
||||
PersistentPropertyPathExtension path1 = extPath("withId"); |
||||
PersistentPropertyPathExtension path2 = extPath("withId"); |
||||
|
||||
assertSoftly(softly -> { |
||||
|
||||
softly.assertThat(root1).describedAs("root is equal to self").isEqualTo(root1); |
||||
softly.assertThat(root2).describedAs("root is equal to identical root").isEqualTo(root1); |
||||
softly.assertThat(path1).describedAs("path is equal to self").isEqualTo(path1); |
||||
softly.assertThat(path2).describedAs("path is equal to identical path").isEqualTo(path1); |
||||
softly.assertThat(path1).describedAs("path is not equal to other path").isNotEqualTo(extPath("entityId")); |
||||
softly.assertThat(root1).describedAs("root is not equal to path").isNotEqualTo(path1); |
||||
softly.assertThat(path1).describedAs("path is not equal to root").isNotEqualTo(root1); |
||||
}); |
||||
} |
||||
|
||||
@Test // GH-1249
|
||||
void isWritable() { |
||||
|
||||
assertSoftly(softly -> { |
||||
softly.assertThat(PersistentPropertyPathExtension.isWritable(createSimplePath("withId"))) |
||||
.describedAs("simple path is writable").isTrue(); |
||||
softly.assertThat(PersistentPropertyPathExtension.isWritable(createSimplePath("secondList.third2"))) |
||||
.describedAs("long path is writable").isTrue(); |
||||
softly.assertThat(PersistentPropertyPathExtension.isWritable(createSimplePath("second"))) |
||||
.describedAs("simple read only path is not writable").isFalse(); |
||||
softly.assertThat(PersistentPropertyPathExtension.isWritable(createSimplePath("second.third"))) |
||||
.describedAs("long path containing read only element is not writable").isFalse(); |
||||
}); |
||||
} |
||||
|
||||
@Test // GH-1525
|
||||
void getAggregatePath() { |
||||
assertThat(extPath("withId").getAggregatePath()).isNotNull(); |
||||
} |
||||
@Test // GH-1525
|
||||
void getAggregatePathFromRoot() { |
||||
assertThat(extPath(entity).getAggregatePath()).isNotNull(); |
||||
} |
||||
private PersistentPropertyPathExtension extPath(RelationalPersistentEntity<?> entity) { |
||||
return new PersistentPropertyPathExtension(context, entity); |
||||
} |
||||
|
||||
private PersistentPropertyPathExtension extPath(String path) { |
||||
return new PersistentPropertyPathExtension(context, createSimplePath(path)); |
||||
} |
||||
|
||||
PersistentPropertyPath<RelationalPersistentProperty> createSimplePath(String path) { |
||||
return PersistentPropertyPathTestUtils.getPath(path, DummyEntity.class, context); |
||||
} |
||||
|
||||
@SuppressWarnings("unused") |
||||
static class DummyEntity { |
||||
@Id Long entityId; |
||||
@ReadOnlyProperty Second second; |
||||
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "sec") Second second2; |
||||
@Embedded(onEmpty = OnEmpty.USE_NULL) Second second3; |
||||
List<Second> secondList; |
||||
WithId withId; |
||||
} |
||||
|
||||
@SuppressWarnings("unused") |
||||
static class Second { |
||||
Third third; |
||||
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "thrd") Third third2; |
||||
} |
||||
|
||||
@SuppressWarnings("unused") |
||||
static class Third { |
||||
String value; |
||||
} |
||||
|
||||
@SuppressWarnings("unused") |
||||
static class WithId { |
||||
@Id Long withIdId; |
||||
Second second; |
||||
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "sec") Second second2; |
||||
} |
||||
|
||||
} |
||||
@ -1,61 +0,0 @@
@@ -1,61 +0,0 @@
|
||||
/* |
||||
* Copyright 2018-2024 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 |
||||
* |
||||
* https://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.data.convert.CustomConversions; |
||||
import org.springframework.data.mapping.context.MappingContext; |
||||
import org.springframework.data.mapping.model.SimpleTypeHolder; |
||||
import org.springframework.data.relational.core.mapping.RelationalMappingContext; |
||||
|
||||
/** |
||||
* {@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 |
||||
* @author Jens Schauder |
||||
* @author Chirag Tailor |
||||
* @author Vincent Galloy |
||||
* @see MappingContext |
||||
* @see SimpleTypeHolder |
||||
* @see CustomConversions |
||||
* @deprecated since 3.2, use {@link MappingRelationalConverter} instead as the naming suggests a limited scope of |
||||
* functionality. |
||||
*/ |
||||
@Deprecated(since = "3.2") |
||||
public class BasicRelationalConverter extends MappingRelationalConverter { |
||||
|
||||
/** |
||||
* Creates a new {@link BasicRelationalConverter} given {@link MappingContext}. |
||||
* |
||||
* @param context must not be {@literal null}. |
||||
*/ |
||||
public BasicRelationalConverter(RelationalMappingContext context) { |
||||
super(context); |
||||
} |
||||
|
||||
/** |
||||
* 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(RelationalMappingContext context, CustomConversions conversions) { |
||||
super(context, conversions); |
||||
} |
||||
|
||||
} |
||||
@ -1,485 +0,0 @@
@@ -1,485 +0,0 @@
|
||||
/* |
||||
* Copyright 2019-2024 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 |
||||
* |
||||
* https://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 java.util.Objects; |
||||
|
||||
import org.springframework.data.mapping.PersistentProperty; |
||||
import org.springframework.data.mapping.PersistentPropertyPath; |
||||
import org.springframework.data.mapping.context.MappingContext; |
||||
import org.springframework.data.relational.core.sql.SqlIdentifier; |
||||
import org.springframework.data.util.Lazy; |
||||
import org.springframework.lang.Nullable; |
||||
import org.springframework.util.Assert; |
||||
import org.springframework.util.StringUtils; |
||||
|
||||
/** |
||||
* A wrapper around a {@link org.springframework.data.mapping.PersistentPropertyPath} for making common operations |
||||
* available used in SQL generation and conversion |
||||
* |
||||
* @author Jens Schauder |
||||
* @author Daniil Razorenov |
||||
* @author Kurt Niemi |
||||
* @since 1.1 |
||||
* @deprecated use {@link AggregatePath} instead |
||||
*/ |
||||
@Deprecated(since = "3.2", forRemoval = true) |
||||
public class PersistentPropertyPathExtension { |
||||
|
||||
private final RelationalPersistentEntity<?> entity; |
||||
private final @Nullable PersistentPropertyPath<? extends RelationalPersistentProperty> path; |
||||
private final MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> context; |
||||
|
||||
private final Lazy<SqlIdentifier> columnAlias = Lazy.of(() -> prefixWithTableAlias(getColumnName())); |
||||
|
||||
/** |
||||
* Creates the empty path referencing the root itself. |
||||
* |
||||
* @param context Must not be {@literal null}. |
||||
* @param entity Root entity of the path. Must not be {@literal null}. |
||||
*/ |
||||
public PersistentPropertyPathExtension( |
||||
MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> context, |
||||
RelationalPersistentEntity<?> entity) { |
||||
|
||||
Assert.notNull(context, "Context must not be null"); |
||||
Assert.notNull(entity, "Entity must not be null"); |
||||
|
||||
this.context = context; |
||||
this.entity = entity; |
||||
this.path = null; |
||||
} |
||||
|
||||
/** |
||||
* Creates a non-empty path. |
||||
* |
||||
* @param context must not be {@literal null}. |
||||
* @param path must not be {@literal null}. |
||||
*/ |
||||
public PersistentPropertyPathExtension( |
||||
MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> context, |
||||
PersistentPropertyPath<? extends RelationalPersistentProperty> path) { |
||||
|
||||
Assert.notNull(context, "Context must not be null"); |
||||
Assert.notNull(path, "Path must not be null"); |
||||
Assert.notNull(path.getBaseProperty(), "Path must not be empty."); |
||||
|
||||
this.context = context; |
||||
this.entity = path.getBaseProperty().getOwner(); |
||||
this.path = path; |
||||
} |
||||
|
||||
public static boolean isWritable(@Nullable PersistentPropertyPath<? extends RelationalPersistentProperty> path) { |
||||
return path == null || path.getLeafProperty().isWritable() && isWritable(path.getParentPath()); |
||||
} |
||||
|
||||
/** |
||||
* Returns {@literal true} exactly when the path is non-empty and the leaf property an embedded one. |
||||
* |
||||
* @return if the leaf property is embedded. |
||||
*/ |
||||
public boolean isEmbedded() { |
||||
return path != null && path.getLeafProperty().isEmbedded(); |
||||
} |
||||
|
||||
/** |
||||
* Returns the path that has the same beginning but is one segment shorter than this path. |
||||
* |
||||
* @return the parent path. Guaranteed to be not {@literal null}. |
||||
* @throws IllegalStateException when called on an empty path. |
||||
*/ |
||||
public PersistentPropertyPathExtension getParentPath() { |
||||
|
||||
if (path == null) { |
||||
throw new IllegalStateException("The parent path of a root path is not defined."); |
||||
} |
||||
|
||||
if (path.getLength() == 1) { |
||||
return new PersistentPropertyPathExtension(context, entity); |
||||
} |
||||
|
||||
return new PersistentPropertyPathExtension(context, path.getParentPath()); |
||||
} |
||||
|
||||
/** |
||||
* Returns {@literal true} if there are multiple values for this path, i.e. if the path contains at least one element |
||||
* that is a collection and array or a map. |
||||
* |
||||
* @return {@literal true} if the path contains a multivalued element. |
||||
*/ |
||||
public boolean isMultiValued() { |
||||
|
||||
return path != null && //
|
||||
(path.getLeafProperty().isCollectionLike() //
|
||||
|| path.getLeafProperty().isQualified() //
|
||||
|| getParentPath().isMultiValued() //
|
||||
); |
||||
} |
||||
|
||||
/** |
||||
* The {@link RelationalPersistentEntity} associated with the leaf of this path. |
||||
* |
||||
* @return Might return {@literal null} when called on a path that does not represent an entity. |
||||
*/ |
||||
@Nullable |
||||
public RelationalPersistentEntity<?> getLeafEntity() { |
||||
return path == null ? entity |
||||
: context.getPersistentEntity(path.getLeafProperty().getTypeInformation().getActualType()); |
||||
} |
||||
|
||||
/** |
||||
* The {@link RelationalPersistentEntity} associated with the leaf of this path or throw {@link IllegalStateException} |
||||
* if the leaf cannot be resolved. |
||||
* |
||||
* @return the required {@link RelationalPersistentEntity} associated with the leaf of this path. |
||||
* @since 3.0 |
||||
* @throws IllegalStateException if the persistent entity cannot be resolved. |
||||
*/ |
||||
public RelationalPersistentEntity<?> getRequiredLeafEntity() { |
||||
|
||||
RelationalPersistentEntity<?> entity = getLeafEntity(); |
||||
|
||||
if (entity == null) { |
||||
|
||||
if (this.path == null) { |
||||
throw new IllegalStateException("Couldn't resolve leaf PersistentEntity absent path"); |
||||
} |
||||
throw new IllegalStateException( |
||||
String.format("Couldn't resolve leaf PersistentEntity for type %s", path.getLeafProperty().getActualType())); |
||||
} |
||||
|
||||
return entity; |
||||
} |
||||
|
||||
/** |
||||
* @return {@literal true} when this is an empty path or the path references an entity. |
||||
*/ |
||||
public boolean isEntity() { |
||||
return path == null || path.getLeafProperty().isEntity(); |
||||
} |
||||
|
||||
/** |
||||
* @return {@literal true} when this is references a {@link java.util.List} or {@link java.util.Map}. |
||||
*/ |
||||
public boolean isQualified() { |
||||
return path != null && path.getLeafProperty().isQualified(); |
||||
} |
||||
|
||||
/** |
||||
* @return {@literal true} when this is references a {@link java.util.Collection} or an array. |
||||
*/ |
||||
public boolean isCollectionLike() { |
||||
return path != null && path.getLeafProperty().isCollectionLike(); |
||||
} |
||||
|
||||
/** |
||||
* The name of the column used to reference the id in the parent table. |
||||
* |
||||
* @throws IllegalStateException when called on an empty path. |
||||
*/ |
||||
public SqlIdentifier getReverseColumnName() { |
||||
|
||||
Assert.state(path != null, "Empty paths don't have a reverse column name"); |
||||
return path.getLeafProperty().getReverseColumnName(this); |
||||
} |
||||
|
||||
/** |
||||
* The alias used in select for the column used to reference the id in the parent table. |
||||
* |
||||
* @throws IllegalStateException when called on an empty path. |
||||
*/ |
||||
public SqlIdentifier getReverseColumnNameAlias() { |
||||
|
||||
return prefixWithTableAlias(getReverseColumnName()); |
||||
} |
||||
|
||||
/** |
||||
* The name of the column used to represent this property in the database. |
||||
* |
||||
* @throws IllegalStateException when called on an empty path. |
||||
*/ |
||||
public SqlIdentifier getColumnName() { |
||||
|
||||
Assert.state(path != null, "Path is null"); |
||||
|
||||
return path.getLeafProperty().getColumnName(); |
||||
} |
||||
|
||||
/** |
||||
* The alias for the column used to represent this property in the database. |
||||
* |
||||
* @throws IllegalStateException when called on an empty path. |
||||
*/ |
||||
public SqlIdentifier getColumnAlias() { |
||||
return columnAlias.get(); |
||||
} |
||||
|
||||
/** |
||||
* @return {@literal true} if this path represents an entity which has an Id attribute. |
||||
*/ |
||||
public boolean hasIdProperty() { |
||||
|
||||
RelationalPersistentEntity<?> leafEntity = getLeafEntity(); |
||||
return leafEntity != null && leafEntity.hasIdProperty(); |
||||
} |
||||
|
||||
/** |
||||
* Returns the longest ancestor path that has an {@link org.springframework.data.annotation.Id} property. |
||||
* |
||||
* @return A path that starts just as this path but is shorter. Guaranteed to be not {@literal null}. |
||||
*/ |
||||
public PersistentPropertyPathExtension getIdDefiningParentPath() { |
||||
|
||||
PersistentPropertyPathExtension parent = getParentPath(); |
||||
|
||||
if (parent.path == null) { |
||||
return parent; |
||||
} |
||||
|
||||
if (!parent.hasIdProperty()) { |
||||
return parent.getIdDefiningParentPath(); |
||||
} |
||||
|
||||
return parent; |
||||
} |
||||
|
||||
/** |
||||
* The fully qualified name of the table this path is tied to or of the longest ancestor path that is actually tied to |
||||
* a table. |
||||
* |
||||
* @return the name of the table. Guaranteed to be not {@literal null}. |
||||
* @since 3.0 |
||||
*/ |
||||
public SqlIdentifier getQualifiedTableName() { |
||||
return getTableOwningAncestor().getRequiredLeafEntity().getQualifiedTableName(); |
||||
} |
||||
|
||||
/** |
||||
* The name of the table this path is tied to or of the longest ancestor path that is actually tied to a table. |
||||
* |
||||
* @return the name of the table. Guaranteed to be not {@literal null}. |
||||
* @since 3.0 |
||||
*/ |
||||
public SqlIdentifier getTableName() { |
||||
return getTableOwningAncestor().getRequiredLeafEntity().getTableName(); |
||||
} |
||||
|
||||
/** |
||||
* The alias used for the table on which this path is based. |
||||
* |
||||
* @return a table alias, {@literal null} if the table owning path is the empty path. |
||||
*/ |
||||
@Nullable |
||||
public SqlIdentifier getTableAlias() { |
||||
|
||||
PersistentPropertyPathExtension tableOwner = getTableOwningAncestor(); |
||||
|
||||
return tableOwner.path == null ? null : tableOwner.assembleTableAlias(); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* The column name of the id column of the ancestor path that represents an actual table. |
||||
*/ |
||||
public SqlIdentifier getIdColumnName() { |
||||
return getTableOwningAncestor().getRequiredLeafEntity().getIdColumn(); |
||||
} |
||||
|
||||
/** |
||||
* If the table owning ancestor has an id the column name of that id property is returned. Otherwise the reverse |
||||
* column is returned. |
||||
*/ |
||||
public SqlIdentifier getEffectiveIdColumnName() { |
||||
|
||||
PersistentPropertyPathExtension owner = getTableOwningAncestor(); |
||||
return owner.path == null ? owner.getRequiredLeafEntity().getIdColumn() : owner.getReverseColumnName(); |
||||
} |
||||
|
||||
/** |
||||
* The length of the path. |
||||
*/ |
||||
public int getLength() { |
||||
return path == null ? 0 : path.getLength(); |
||||
} |
||||
|
||||
/** |
||||
* Tests if {@code this} and the argument represent the same path. |
||||
* |
||||
* @param path to which this path gets compared. May be {@literal null}. |
||||
* @return Whence the argument matches the path represented by this instance. |
||||
*/ |
||||
public boolean matches(PersistentPropertyPath<RelationalPersistentProperty> path) { |
||||
return this.path == null ? path.isEmpty() : this.path.equals(path); |
||||
} |
||||
|
||||
/** |
||||
* The id property of the final element of the path. |
||||
* |
||||
* @return Guaranteed to be not {@literal null}. |
||||
* @throws IllegalStateException if no such property exists. |
||||
*/ |
||||
public RelationalPersistentProperty getRequiredIdProperty() { |
||||
return this.path == null ? entity.getRequiredIdProperty() : getRequiredLeafEntity().getRequiredIdProperty(); |
||||
} |
||||
|
||||
/** |
||||
* The column name used for the list index or map key of the leaf property of this path. |
||||
* |
||||
* @return May be {@literal null}. |
||||
*/ |
||||
@Nullable |
||||
public SqlIdentifier getQualifierColumn() { |
||||
return path == null ? SqlIdentifier.EMPTY : path.getLeafProperty().getKeyColumn(); |
||||
} |
||||
|
||||
/** |
||||
* The type of the qualifier column of the leaf property of this path or {@literal null} if this is not applicable. |
||||
* |
||||
* @return may be {@literal null}. |
||||
*/ |
||||
@Nullable |
||||
public Class<?> getQualifierColumnType() { |
||||
return path == null ? null : path.getLeafProperty().getQualifierColumnType(); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new path by extending the current path by the property passed as an argument. |
||||
* |
||||
* @param property must not be {@literal null}. |
||||
* @return Guaranteed to be not {@literal null}. |
||||
*/ |
||||
public PersistentPropertyPathExtension extendBy(RelationalPersistentProperty property) { |
||||
|
||||
PersistentPropertyPath<? extends RelationalPersistentProperty> newPath = path == null //
|
||||
? context.getPersistentPropertyPath(property.getName(), entity.getTypeInformation()) //
|
||||
: context.getPersistentPropertyPath(path.toDotPath() + "." + property.getName(), entity.getTypeInformation()); |
||||
|
||||
return new PersistentPropertyPathExtension(context, newPath); |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return String.format("PersistentPropertyPathExtension[%s, %s]", entity.getName(), |
||||
path == null ? "-" : path.toDotPath()); |
||||
} |
||||
|
||||
/** |
||||
* For empty paths this is the type of the entity. For non empty paths this is the actual type of the leaf property. |
||||
* |
||||
* @return Guaranteed to be not {@literal null}. |
||||
* @see PersistentProperty#getActualType() |
||||
*/ |
||||
public Class<?> getActualType() { |
||||
|
||||
return path == null //
|
||||
? entity.getType() //
|
||||
: path.getLeafProperty().getActualType(); |
||||
} |
||||
|
||||
/** |
||||
* @return {@literal true} if the leaf property of this path is a {@link java.util.Map}. |
||||
* @see RelationalPersistentProperty#isMap() |
||||
*/ |
||||
public boolean isMap() { |
||||
return path != null && path.getLeafProperty().isMap(); |
||||
} |
||||
|
||||
/** |
||||
* Converts this path to a non-null {@link PersistentPropertyPath}. |
||||
* |
||||
* @return Guaranteed to be not {@literal null}. |
||||
* @throws IllegalStateException if this path is empty. |
||||
*/ |
||||
public PersistentPropertyPath<? extends RelationalPersistentProperty> getRequiredPersistentPropertyPath() { |
||||
|
||||
Assert.state(path != null, "No path."); |
||||
|
||||
return path; |
||||
} |
||||
|
||||
/** |
||||
* Finds and returns the longest path with ich identical or an ancestor to the current path and maps directly to a |
||||
* table. |
||||
* |
||||
* @return a path. Guaranteed to be not {@literal null}. |
||||
*/ |
||||
private PersistentPropertyPathExtension getTableOwningAncestor() { |
||||
|
||||
return isEntity() && !isEmbedded() ? this : getParentPath().getTableOwningAncestor(); |
||||
} |
||||
|
||||
@Nullable |
||||
private SqlIdentifier assembleTableAlias() { |
||||
|
||||
Assert.state(path != null, "Path is null"); |
||||
|
||||
RelationalPersistentProperty leafProperty = path.getLeafProperty(); |
||||
String prefix; |
||||
if (isEmbedded()) { |
||||
prefix = leafProperty.getEmbeddedPrefix(); |
||||
|
||||
} else { |
||||
prefix = leafProperty.getName(); |
||||
} |
||||
|
||||
if (path.getLength() == 1) { |
||||
Assert.notNull(prefix, "Prefix mus not be null"); |
||||
return StringUtils.hasText(prefix) ? SqlIdentifier.quoted(prefix) : null; |
||||
} |
||||
|
||||
PersistentPropertyPathExtension parentPath = getParentPath(); |
||||
SqlIdentifier sqlIdentifier = parentPath.assembleTableAlias(); |
||||
|
||||
if (sqlIdentifier != null) { |
||||
|
||||
return parentPath.isEmbedded() ? sqlIdentifier.transform(name -> name.concat(prefix)) |
||||
: sqlIdentifier.transform(name -> name + "_" + prefix); |
||||
} |
||||
return SqlIdentifier.quoted(prefix); |
||||
|
||||
} |
||||
|
||||
private SqlIdentifier prefixWithTableAlias(SqlIdentifier columnName) { |
||||
|
||||
SqlIdentifier tableAlias = getTableAlias(); |
||||
return tableAlias == null ? columnName : columnName.transform(name -> tableAlias.getReference() + "_" + name); |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(@Nullable Object o) { |
||||
|
||||
if (this == o) |
||||
return true; |
||||
if (o == null || getClass() != o.getClass()) |
||||
return false; |
||||
PersistentPropertyPathExtension that = (PersistentPropertyPathExtension) o; |
||||
return entity.equals(that.entity) && Objects.equals(path, that.path); |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
return Objects.hash(entity, path); |
||||
} |
||||
|
||||
public AggregatePath getAggregatePath() { |
||||
if (path != null) { |
||||
|
||||
return ((RelationalMappingContext) context).getAggregatePath(path); |
||||
} else { |
||||
return ((RelationalMappingContext) context).getAggregatePath(entity); |
||||
} |
||||
} |
||||
} |
||||
@ -1,174 +0,0 @@
@@ -1,174 +0,0 @@
|
||||
/* |
||||
* Copyright 2018-2024 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 |
||||
* |
||||
* https://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 java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
import java.util.function.Function; |
||||
|
||||
import org.junit.jupiter.api.BeforeEach; |
||||
import org.junit.jupiter.api.Test; |
||||
import org.springframework.data.convert.ConverterBuilder; |
||||
import org.springframework.data.convert.ConverterBuilder.ConverterAware; |
||||
import org.springframework.data.convert.CustomConversions; |
||||
import org.springframework.data.mapping.PersistentPropertyAccessor; |
||||
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.TypeInformation; |
||||
|
||||
/** |
||||
* Unit tests for {@link BasicRelationalConverter}. |
||||
* |
||||
* @author Mark Paluch |
||||
* @author Chirag Tailor |
||||
*/ |
||||
class BasicRelationalConverterUnitTests { |
||||
|
||||
RelationalMappingContext context = new RelationalMappingContext(); |
||||
RelationalConverter converter; |
||||
|
||||
@BeforeEach |
||||
public void before() throws Exception { |
||||
|
||||
List<Object> converters = new ArrayList<>(); |
||||
converters.addAll( |
||||
ConverterBuilder.writing(MyValue.class, String.class, MyValue::foo).andReading(MyValue::new).getConverters()); |
||||
|
||||
ConverterAware converterAware = ConverterBuilder |
||||
.writing(MySimpleEnum.class, MySimpleEnum.class, Function.identity()).andReading(mySimpleEnum -> mySimpleEnum); |
||||
converters.addAll(converterAware.getConverters()); |
||||
|
||||
CustomConversions conversions = new CustomConversions(CustomConversions.StoreConversions.NONE, converters); |
||||
context.setSimpleTypeHolder(conversions.getSimpleTypeHolder()); |
||||
|
||||
converter = new BasicRelationalConverter(context, conversions); |
||||
} |
||||
|
||||
@Test // DATAJDBC-235
|
||||
@SuppressWarnings("unchecked") |
||||
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.flag).isTrue(); |
||||
} |
||||
|
||||
@Test // DATAJDBC-235
|
||||
void shouldConvertEnumToString() { |
||||
|
||||
Object result = converter.writeValue(MyEnum.ON, TypeInformation.of(String.class)); |
||||
|
||||
assertThat(result).isEqualTo("ON"); |
||||
} |
||||
|
||||
@Test |
||||
void shouldConvertEnumArrayToStringArray() { |
||||
|
||||
Object result = converter.writeValue(new MyEnum[] { MyEnum.ON }, TypeInformation.OBJECT); |
||||
|
||||
assertThat(result).isEqualTo(new String[] { "ON" }); |
||||
} |
||||
|
||||
@Test // GH-1593
|
||||
void shouldRetainEnumArray() { |
||||
|
||||
Object result = converter.writeValue(new MySimpleEnum[] { MySimpleEnum.ON }, TypeInformation.OBJECT); |
||||
|
||||
assertThat(result).isEqualTo(new MySimpleEnum[] { MySimpleEnum.ON }); |
||||
} |
||||
|
||||
@Test // GH-1593
|
||||
void shouldConvertStringToEnum() { |
||||
|
||||
Object result = converter.readValue("OFF", TypeInformation.of(MyEnum.class)); |
||||
|
||||
assertThat(result).isEqualTo(MyEnum.OFF); |
||||
} |
||||
|
||||
@Test // GH-1046
|
||||
void shouldConvertArrayElementsToTargetElementType() throws NoSuchMethodException { |
||||
|
||||
TypeInformation<?> typeInformation = TypeInformation.fromReturnTypeOf(EntityWithArray.class.getMethod("floats")); |
||||
Double[] value = { 1.2d, 1.3d, 1.4d }; |
||||
Object result = converter.readValue(value, typeInformation); |
||||
assertThat(result).isEqualTo(Arrays.asList(1.2f, 1.3f, 1.4f)); |
||||
} |
||||
|
||||
@Test // DATAJDBC-235
|
||||
@SuppressWarnings("unchecked") |
||||
void shouldCreateInstance() { |
||||
|
||||
RelationalPersistentEntity<WithConstructorCreation> entity = (RelationalPersistentEntity) context |
||||
.getRequiredPersistentEntity(WithConstructorCreation.class); |
||||
|
||||
WithConstructorCreation result = converter.createInstance(entity, it -> "bar"); |
||||
|
||||
assertThat(result.foo).isEqualTo("bar"); |
||||
} |
||||
|
||||
@Test // DATAJDBC-516
|
||||
void shouldConsiderWriteConverter() { |
||||
|
||||
Object result = converter.writeValue(new MyValue("hello-world"), TypeInformation.of(String.class)); |
||||
|
||||
assertThat(result).isEqualTo("hello-world"); |
||||
} |
||||
|
||||
@Test // DATAJDBC-516
|
||||
void shouldConsiderReadConverter() { |
||||
|
||||
Object result = converter.readValue("hello-world", TypeInformation.of(MyValue.class)); |
||||
|
||||
assertThat(result).isEqualTo(new MyValue("hello-world")); |
||||
} |
||||
|
||||
record EntityWithArray(List<Float> floats) { |
||||
} |
||||
|
||||
static class MyEntity { |
||||
boolean flag; |
||||
} |
||||
|
||||
record WithConstructorCreation(String foo) { |
||||
} |
||||
|
||||
record MyValue(String foo) { |
||||
} |
||||
|
||||
static class MyEntityWithConvertibleProperty { |
||||
|
||||
MyValue myValue; |
||||
} |
||||
|
||||
enum MyEnum { |
||||
ON, OFF; |
||||
} |
||||
|
||||
enum MySimpleEnum { |
||||
ON, OFF; |
||||
} |
||||
} |
||||
Loading…
Reference in new issue