Browse Source

Move Sequence to RelationalPersistentProperty.

Sequence details are now maintained on the property level instead of using the entity level. This is a more accurate representation of the underlying model and that properties are annotated and not entities. It also allows future extension of expanding sequence support to general properties.

Extract delegate for sequence generation. Move types to org.springframework.data.jdbc.core.convert to resolve package cycles.

See #2003
Original pull request: #2005
pull/2034/head
Mark Paluch 8 months ago
parent
commit
eb25cc3ed4
No known key found for this signature in database
GPG Key ID: 55BC6374BAA9D973
  1. 71
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/IdGeneratingEntityCallback.java
  2. 102
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SequenceEntityCallbackDelegate.java
  3. 112
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/mapping/IdGeneratingBeforeSaveCallback.java
  4. 8
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfiguration.java
  5. 18
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/IdGeneratingEntityCallbackTest.java
  6. 4
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryIdGenerationIntegrationTests.java
  7. 9
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/TestConfiguration.java
  8. 5
      spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/IdValueSource.java
  9. 36
      spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentEntity.java
  10. 32
      spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentProperty.java
  11. 6
      spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/EmbeddedRelationalPersistentEntity.java
  12. 6
      spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/EmbeddedRelationalPersistentProperty.java
  13. 8
      spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/RelationalPersistentEntity.java
  14. 17
      spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/RelationalPersistentProperty.java
  15. 56
      spring-data-relational/src/test/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentEntityUnitTests.java
  16. 207
      spring-data-relational/src/test/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentPropertyUnitTests.java

71
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/IdGeneratingEntityCallback.java

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
/*
* Copyright 2025 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.mapping.PersistentPropertyAccessor;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.relational.core.conversion.MutableAggregateChange;
import org.springframework.data.relational.core.dialect.Dialect;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
import org.springframework.data.relational.core.mapping.event.BeforeSaveCallback;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.util.Assert;
/**
* Callback for generating identifier values through a database sequence.
*
* @author Mikhail Polivakha
* @author Mark Paluch
* @since 3.5
*/
public class IdGeneratingEntityCallback implements BeforeSaveCallback<Object> {
private final MappingContext<RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> context;
private final SequenceEntityCallbackDelegate delegate;
public IdGeneratingEntityCallback(
MappingContext<RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> context, Dialect dialect,
NamedParameterJdbcOperations operations) {
this.context = context;
this.delegate = new SequenceEntityCallbackDelegate(dialect, operations);
}
@Override
public Object onBeforeSave(Object aggregate, MutableAggregateChange<Object> aggregateChange) {
Assert.notNull(aggregate, "aggregate must not be null");
RelationalPersistentEntity<?> entity = context.getRequiredPersistentEntity(aggregate.getClass());
if (!entity.hasIdProperty()) {
return aggregate;
}
RelationalPersistentProperty property = entity.getRequiredIdProperty();
PersistentPropertyAccessor<Object> accessor = entity.getPropertyAccessor(aggregate);
if (!entity.isNew(aggregate) || delegate.hasValue(property, accessor) || !property.hasSequence()) {
return aggregate;
}
delegate.generateSequenceValue(property, accessor);
return accessor.getBean();
}
}

102
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SequenceEntityCallbackDelegate.java

@ -0,0 +1,102 @@ @@ -0,0 +1,102 @@
/*
* Copyright 2025 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.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.relational.core.dialect.Dialect;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.data.util.ReflectionUtils;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.NumberUtils;
/**
* Support class for generating identifier values through a database sequence.
*
* @author Mikhail Polivakha
* @author Mark Paluch
* @since 3.5
* @see org.springframework.data.relational.core.mapping.Sequence
*/
class SequenceEntityCallbackDelegate {
private static final Log LOG = LogFactory.getLog(SequenceEntityCallbackDelegate.class);
private final static MapSqlParameterSource EMPTY_PARAMETERS = new MapSqlParameterSource();
private final Dialect dialect;
private final NamedParameterJdbcOperations operations;
public SequenceEntityCallbackDelegate(Dialect dialect, NamedParameterJdbcOperations operations) {
this.dialect = dialect;
this.operations = operations;
}
@SuppressWarnings("unchecked")
protected void generateSequenceValue(RelationalPersistentProperty property,
PersistentPropertyAccessor<Object> accessor) {
Object sequenceValue = getSequenceValue(property);
if (sequenceValue == null) {
return;
}
Class<?> targetType = ClassUtils.resolvePrimitiveIfNecessary(property.getType());
if (sequenceValue instanceof Number && Number.class.isAssignableFrom(targetType)) {
sequenceValue = NumberUtils.convertNumberToTargetClass((Number) sequenceValue,
(Class<? extends Number>) targetType);
}
accessor.setProperty(property, sequenceValue);
}
protected boolean hasValue(PersistentProperty<?> property, PersistentPropertyAccessor<Object> propertyAccessor) {
Object identifier = propertyAccessor.getProperty(property);
if (property.getType().isPrimitive()) {
Object primitiveDefault = ReflectionUtils.getPrimitiveDefault(property.getType());
return !primitiveDefault.equals(identifier);
}
return identifier != null;
}
private @Nullable Object getSequenceValue(RelationalPersistentProperty property) {
SqlIdentifier sequence = property.getSequence();
if (sequence != null && !dialect.getIdGeneration().sequencesSupported()) {
LOG.warn("""
Aggregate type '%s' is marked for sequence usage but configured dialect '%s'
does not support sequences. Falling back to identity columns.
""".formatted(property.getOwner().getType(), ClassUtils.getQualifiedName(dialect.getClass())));
return null;
}
String sql = dialect.getIdGeneration().createSequenceQuery(sequence);
return operations.queryForObject(sql, EMPTY_PARAMETERS, (rs, rowNum) -> rs.getObject(1));
}
}

112
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/mapping/IdGeneratingBeforeSaveCallback.java

@ -1,112 +0,0 @@ @@ -1,112 +0,0 @@
package org.springframework.data.jdbc.core.mapping;
import java.util.Optional;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.relational.core.conversion.MutableAggregateChange;
import org.springframework.data.relational.core.dialect.Dialect;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
import org.springframework.data.relational.core.mapping.event.BeforeSaveCallback;
import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.data.util.ReflectionUtils;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.NumberUtils;
/**
* Callback for generating identifier values through a database sequence.
*
* @author Mikhail Polivakha
* @author Mark Paluch
* @since 3.5
* @see org.springframework.data.relational.core.mapping.Sequence
*/
public class IdGeneratingBeforeSaveCallback implements BeforeSaveCallback<Object> {
private static final Log LOG = LogFactory.getLog(IdGeneratingBeforeSaveCallback.class);
private final static MapSqlParameterSource EMPTY_PARAMETERS = new MapSqlParameterSource();
private final MappingContext<RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> mappingContext;
private final Dialect dialect;
private final NamedParameterJdbcOperations operations;
public IdGeneratingBeforeSaveCallback(
MappingContext<RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> mappingContext,
Dialect dialect, NamedParameterJdbcOperations operations) {
this.mappingContext = mappingContext;
this.dialect = dialect;
this.operations = operations;
}
@Override
public Object onBeforeSave(Object aggregate, MutableAggregateChange<Object> aggregateChange) {
Assert.notNull(aggregate, "aggregate must not be null");
RelationalPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(aggregate.getClass());
if (!entity.hasIdProperty()) {
return aggregate;
}
RelationalPersistentProperty idProperty = entity.getRequiredIdProperty();
PersistentPropertyAccessor<Object> accessor = entity.getPropertyAccessor(aggregate);
if (!entity.isNew(aggregate) || hasIdentifierValue(idProperty, accessor)) {
return aggregate;
}
potentiallyFetchIdFromSequence(idProperty, entity, accessor);
return accessor.getBean();
}
private boolean hasIdentifierValue(PersistentProperty<?> idProperty,
PersistentPropertyAccessor<Object> propertyAccessor) {
Object identifier = propertyAccessor.getProperty(idProperty);
if (idProperty.getType().isPrimitive()) {
Object primitiveDefault = ReflectionUtils.getPrimitiveDefault(idProperty.getType());
return !primitiveDefault.equals(identifier);
}
return identifier != null;
}
@SuppressWarnings("unchecked")
private void potentiallyFetchIdFromSequence(PersistentProperty<?> idProperty,
RelationalPersistentEntity<?> persistentEntity, PersistentPropertyAccessor<Object> accessor) {
Optional<SqlIdentifier> idSequence = persistentEntity.getIdSequence();
if (idSequence.isPresent() && !dialect.getIdGeneration().sequencesSupported()) {
LOG.warn("""
Aggregate type '%s' is marked for sequence usage but configured dialect '%s'
does not support sequences. Falling back to identity columns.
""".formatted(persistentEntity.getType(), ClassUtils.getQualifiedName(dialect.getClass())));
return;
}
idSequence.map(s -> dialect.getIdGeneration().createSequenceQuery(s)).ifPresent(sql -> {
Object idValue = operations.queryForObject(sql, EMPTY_PARAMETERS, (rs, rowNum) -> rs.getObject(1));
Class<?> targetType = ClassUtils.resolvePrimitiveIfNecessary(idProperty.getType());
if (idValue instanceof Number && Number.class.isAssignableFrom(targetType)) {
accessor.setProperty(idProperty,
NumberUtils.convertNumberToTargetClass((Number) idValue, (Class<? extends Number>) targetType));
} else {
accessor.setProperty(idProperty, idValue);
}
});
}
}

8
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfiguration.java

@ -25,6 +25,7 @@ import java.util.Set; @@ -25,6 +25,7 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
@ -38,7 +39,6 @@ import org.springframework.data.jdbc.core.JdbcAggregateOperations; @@ -38,7 +39,6 @@ import org.springframework.data.jdbc.core.JdbcAggregateOperations;
import org.springframework.data.jdbc.core.JdbcAggregateTemplate;
import org.springframework.data.jdbc.core.convert.*;
import org.springframework.data.jdbc.core.dialect.JdbcDialect;
import org.springframework.data.jdbc.core.mapping.IdGeneratingBeforeSaveCallback;
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
import org.springframework.data.jdbc.core.mapping.JdbcSimpleTypes;
import org.springframework.data.mapping.model.SimpleTypeHolder;
@ -121,7 +121,7 @@ public class AbstractJdbcConfiguration implements ApplicationContextAware { @@ -121,7 +121,7 @@ public class AbstractJdbcConfiguration implements ApplicationContextAware {
}
/**
* Creates a {@link IdGeneratingBeforeSaveCallback} bean using the configured
* Creates a {@link IdGeneratingEntityCallback} bean using the configured
* {@link #jdbcMappingContext(Optional, JdbcCustomConversions, RelationalManagedTypes)} and
* {@link #jdbcDialect(NamedParameterJdbcOperations)}.
*
@ -129,9 +129,9 @@ public class AbstractJdbcConfiguration implements ApplicationContextAware { @@ -129,9 +129,9 @@ public class AbstractJdbcConfiguration implements ApplicationContextAware {
* @since 3.5
*/
@Bean
public IdGeneratingBeforeSaveCallback idGeneratingBeforeSaveCallback(JdbcMappingContext mappingContext,
public IdGeneratingEntityCallback idGeneratingBeforeSaveCallback(JdbcMappingContext mappingContext,
NamedParameterJdbcOperations operations, Dialect dialect) {
return new IdGeneratingBeforeSaveCallback(mappingContext, dialect, operations);
return new IdGeneratingEntityCallback(mappingContext, dialect, operations);
}
/**

18
spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/mapping/IdGeneratingBeforeSaveCallbackTest.java → spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/IdGeneratingEntityCallbackTest.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2024-2025 the original author or authors.
* Copyright 2025 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.
@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.jdbc.core.mapping;
package org.springframework.data.jdbc.core.convert;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
@ -41,13 +41,13 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; @@ -41,13 +41,13 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
/**
* Unit tests for {@link IdGeneratingBeforeSaveCallback}
* Unit tests for {@link IdGeneratingEntityCallback}
*
* @author Mikhail Polivakha
* @author Mark Paluch
*/
@MockitoSettings(strictness = Strictness.LENIENT)
class IdGeneratingBeforeSaveCallbackTest {
class IdGeneratingEntityCallbackTest {
@Mock NamedParameterJdbcOperations operations;
RelationalMappingContext relationalMappingContext;
@ -64,7 +64,7 @@ class IdGeneratingBeforeSaveCallbackTest { @@ -64,7 +64,7 @@ class IdGeneratingBeforeSaveCallbackTest {
NamedParameterJdbcOperations operations = mock(NamedParameterJdbcOperations.class);
IdGeneratingBeforeSaveCallback subject = new IdGeneratingBeforeSaveCallback(relationalMappingContext,
IdGeneratingEntityCallback subject = new IdGeneratingEntityCallback(relationalMappingContext,
MySqlDialect.INSTANCE, operations);
EntityWithSequence processed = (EntityWithSequence) subject.onBeforeSave(new EntityWithSequence(),
@ -76,7 +76,7 @@ class IdGeneratingBeforeSaveCallbackTest { @@ -76,7 +76,7 @@ class IdGeneratingBeforeSaveCallbackTest {
@Test // GH-1923
void entityIsNotMarkedWithTargetSequence() {
IdGeneratingBeforeSaveCallback subject = new IdGeneratingBeforeSaveCallback(relationalMappingContext,
IdGeneratingEntityCallback subject = new IdGeneratingEntityCallback(relationalMappingContext,
MySqlDialect.INSTANCE, operations);
NoSequenceEntity processed = (NoSequenceEntity) subject.onBeforeSave(new NoSequenceEntity(),
@ -92,7 +92,7 @@ class IdGeneratingBeforeSaveCallbackTest { @@ -92,7 +92,7 @@ class IdGeneratingBeforeSaveCallbackTest {
when(operations.queryForObject(anyString(), any(SqlParameterSource.class), any(RowMapper.class)))
.thenReturn(generatedId);
IdGeneratingBeforeSaveCallback subject = new IdGeneratingBeforeSaveCallback(relationalMappingContext,
IdGeneratingEntityCallback subject = new IdGeneratingEntityCallback(relationalMappingContext,
PostgresDialect.INSTANCE, operations);
EntityWithSequence processed = (EntityWithSequence) subject.onBeforeSave(new EntityWithSequence(),
@ -108,7 +108,7 @@ class IdGeneratingBeforeSaveCallbackTest { @@ -108,7 +108,7 @@ class IdGeneratingBeforeSaveCallbackTest {
when(operations.queryForObject(anyString(), any(SqlParameterSource.class), any(RowMapper.class)))
.thenReturn(generatedId);
IdGeneratingBeforeSaveCallback subject = new IdGeneratingBeforeSaveCallback(relationalMappingContext,
IdGeneratingEntityCallback subject = new IdGeneratingEntityCallback(relationalMappingContext,
PostgresDialect.INSTANCE, operations);
EntityWithIntSequence processed = (EntityWithIntSequence) subject.onBeforeSave(new EntityWithIntSequence(),
@ -124,7 +124,7 @@ class IdGeneratingBeforeSaveCallbackTest { @@ -124,7 +124,7 @@ class IdGeneratingBeforeSaveCallbackTest {
when(operations.queryForObject(anyString(), any(SqlParameterSource.class), any(RowMapper.class)))
.thenReturn(generatedId);
IdGeneratingBeforeSaveCallback subject = new IdGeneratingBeforeSaveCallback(relationalMappingContext,
IdGeneratingEntityCallback subject = new IdGeneratingEntityCallback(relationalMappingContext,
PostgresDialect.INSTANCE, operations);
EntityWithUuidSequence processed = (EntityWithUuidSequence) subject.onBeforeSave(new EntityWithUuidSequence(),

4
spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryIdGenerationIntegrationTests.java

@ -35,7 +35,7 @@ import org.springframework.data.annotation.Id; @@ -35,7 +35,7 @@ import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.PersistenceCreator;
import org.springframework.data.annotation.Transient;
import org.springframework.data.domain.Persistable;
import org.springframework.data.jdbc.core.mapping.IdGeneratingBeforeSaveCallback;
import org.springframework.data.jdbc.core.convert.IdGeneratingEntityCallback;
import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories;
import org.springframework.data.jdbc.repository.support.SimpleJdbcRepository;
import org.springframework.data.jdbc.testing.IntegrationTest;
@ -66,7 +66,7 @@ class JdbcRepositoryIdGenerationIntegrationTests { @@ -66,7 +66,7 @@ class JdbcRepositoryIdGenerationIntegrationTests {
@Autowired SimpleSeqRepository simpleSeqRepository;
@Autowired PersistableSeqRepository persistableSeqRepository;
@Autowired PrimitiveIdSeqRepository primitiveIdSeqRepository;
@Autowired IdGeneratingBeforeSaveCallback idGeneratingCallback;
@Autowired IdGeneratingEntityCallback idGeneratingCallback;
@Test // DATAJDBC-98
void idWithoutSetterGetsSet() {

9
spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/TestConfiguration.java

@ -24,6 +24,7 @@ import javax.sql.DataSource; @@ -24,6 +24,7 @@ import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mockito.Mockito;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@ -37,7 +38,6 @@ import org.springframework.context.annotation.Profile; @@ -37,7 +38,6 @@ import org.springframework.context.annotation.Profile;
import org.springframework.data.convert.CustomConversions;
import org.springframework.data.jdbc.core.convert.*;
import org.springframework.data.jdbc.core.dialect.JdbcDialect;
import org.springframework.data.jdbc.core.mapping.IdGeneratingBeforeSaveCallback;
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
import org.springframework.data.jdbc.core.mapping.JdbcSimpleTypes;
import org.springframework.data.jdbc.repository.config.DialectResolver;
@ -45,7 +45,6 @@ import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactory; @@ -45,7 +45,6 @@ import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactory;
import org.springframework.data.mapping.callback.EntityCallback;
import org.springframework.data.mapping.callback.EntityCallbacks;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.relational.RelationalManagedTypes;
import org.springframework.data.relational.core.dialect.Dialect;
import org.springframework.data.relational.core.mapping.DefaultNamingStrategy;
import org.springframework.data.relational.core.mapping.NamingStrategy;
@ -182,15 +181,15 @@ public class TestConfiguration { @@ -182,15 +181,15 @@ public class TestConfiguration {
}
/**
* Creates a {@link IdGeneratingBeforeSaveCallback} bean using the configured
* Creates a {@link IdGeneratingEntityCallback} bean using the configured
* {@link #jdbcDialect(NamedParameterJdbcOperations)}.
*
* @return must not be {@literal null}.
*/
@Bean
public IdGeneratingBeforeSaveCallback idGeneratingBeforeSaveCallback(JdbcMappingContext mappingContext,
public IdGeneratingEntityCallback idGeneratingBeforeSaveCallback(JdbcMappingContext mappingContext,
NamedParameterJdbcOperations operations, Dialect dialect) {
return Mockito.spy(new IdGeneratingBeforeSaveCallback(mappingContext, dialect, operations));
return Mockito.spy(new IdGeneratingEntityCallback(mappingContext, dialect, operations));
}
@Bean

5
spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/IdValueSource.java

@ -49,12 +49,13 @@ public enum IdValueSource { @@ -49,12 +49,13 @@ public enum IdValueSource {
*/
public static <T> IdValueSource forInstance(Object instance, RelationalPersistentEntity<T> persistentEntity) {
if (persistentEntity.getIdSequence().isPresent()) {
RelationalPersistentProperty idProperty = persistentEntity.getIdProperty();
if (idProperty != null && idProperty.hasSequence()) {
return IdValueSource.PROVIDED;
}
Object idValue = persistentEntity.getIdentifierAccessor(instance).getIdentifier();
RelationalPersistentProperty idProperty = persistentEntity.getIdProperty();
if (idProperty == null) {
return IdValueSource.NONE;
}

36
spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentEntity.java

@ -17,8 +17,6 @@ package org.springframework.data.relational.core.mapping; @@ -17,8 +17,6 @@ package org.springframework.data.relational.core.mapping;
import java.util.Optional;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.data.mapping.model.BasicPersistentEntity;
import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.data.util.Lazy;
@ -47,9 +45,6 @@ class BasicRelationalPersistentEntity<T> extends BasicPersistentEntity<T, Relati @@ -47,9 +45,6 @@ class BasicRelationalPersistentEntity<T> extends BasicPersistentEntity<T, Relati
private final Lazy<SqlIdentifier> tableName;
private final @Nullable Expression tableNameExpression;
private final Lazy<SqlIdentifier> idSequenceName;
private final Lazy<Optional<SqlIdentifier>> schemaName;
private final @Nullable Expression schemaNameExpression;
private final ExpressionEvaluator expressionEvaluator;
@ -91,8 +86,6 @@ class BasicRelationalPersistentEntity<T> extends BasicPersistentEntity<T, Relati @@ -91,8 +86,6 @@ class BasicRelationalPersistentEntity<T> extends BasicPersistentEntity<T, Relati
this.schemaName = defaultSchema;
this.schemaNameExpression = null;
}
this.idSequenceName = Lazy.of(this::determineSequenceName);
}
/**
@ -165,38 +158,9 @@ class BasicRelationalPersistentEntity<T> extends BasicPersistentEntity<T, Relati @@ -165,38 +158,9 @@ class BasicRelationalPersistentEntity<T> extends BasicPersistentEntity<T, Relati
return getRequiredIdProperty().getColumnName();
}
@Override
public Optional<SqlIdentifier> getIdSequence() {
return idSequenceName.getOptional();
}
@Override
public String toString() {
return String.format("BasicRelationalPersistentEntity<%s>", getType());
}
private @Nullable SqlIdentifier determineSequenceName() {
RelationalPersistentProperty idProperty = getIdProperty();
if (idProperty != null && idProperty.isAnnotationPresent(Sequence.class)) {
Sequence requiredAnnotation = idProperty.getRequiredAnnotation(Sequence.class);
MergedAnnotation<Sequence> targetSequence = MergedAnnotations.from(requiredAnnotation)
.get(Sequence.class);
String sequence = targetSequence.getString("sequence");
String schema = targetSequence.getString("schema");
SqlIdentifier sequenceIdentifier = SqlIdentifier.quoted(sequence);
if (StringUtils.hasText(schema)) {
sequenceIdentifier = SqlIdentifier.from(SqlIdentifier.quoted(schema), sequenceIdentifier);
}
return sequenceIdentifier;
} else {
return null;
}
}
}

32
spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentProperty.java

@ -52,12 +52,13 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent @@ -52,12 +52,13 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent
private final Lazy<SqlIdentifier> columnName;
private final boolean hasExplicitColumnName;
private final @Nullable Expression columnNameExpression;
private final SqlIdentifier sequence;
private final Lazy<Optional<SqlIdentifier>> collectionIdColumnName;
private final Lazy<SqlIdentifier> collectionKeyColumnName;
private final @Nullable Expression collectionKeyColumnNameExpression;
private final boolean isEmbedded;
private final String embeddedPrefix;
private final NamingStrategy namingStrategy;
private boolean forceQuote = true;
private ExpressionEvaluator expressionEvaluator = new ExpressionEvaluator(EvaluationContextProvider.DEFAULT);
@ -80,7 +81,6 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent @@ -80,7 +81,6 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent
Assert.notNull(namingStrategy, "NamingStrategy must not be null");
this.isEmbedded = isAnnotationPresent(Embedded.class);
this.embeddedPrefix = Optional.ofNullable(findAnnotation(Embedded.class)) //
.map(Embedded::prefix) //
.orElse("");
@ -126,6 +126,8 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent @@ -126,6 +126,8 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent
this.columnNameExpression = null;
}
this.sequence = determineSequenceName();
if (collectionIdColumnName == null) {
collectionIdColumnName = Lazy.of(Optional.empty());
}
@ -269,8 +271,34 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent @@ -269,8 +271,34 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent
return findAnnotation(InsertOnlyProperty.class) != null;
}
@Nullable
@Override
public SqlIdentifier getSequence() {
return this.sequence;
}
private boolean isListLike() {
return isCollectionLike() && !Set.class.isAssignableFrom(this.getType());
}
private @Nullable SqlIdentifier determineSequenceName() {
if (isAnnotationPresent(Sequence.class)) {
Sequence annotation = getRequiredAnnotation(Sequence.class);
String sequence = annotation.sequence();
String schema = annotation.schema();
SqlIdentifier sequenceIdentifier = SqlIdentifier.quoted(sequence);
if (StringUtils.hasText(schema)) {
sequenceIdentifier = SqlIdentifier.from(SqlIdentifier.quoted(schema), sequenceIdentifier);
}
return sequenceIdentifier;
} else {
return null;
}
}
}

6
spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/EmbeddedRelationalPersistentEntity.java

@ -17,7 +17,6 @@ package org.springframework.data.relational.core.mapping; @@ -17,7 +17,6 @@ package org.springframework.data.relational.core.mapping;
import java.lang.annotation.Annotation;
import java.util.Iterator;
import java.util.Optional;
import org.springframework.core.env.Environment;
import org.springframework.data.mapping.*;
@ -56,11 +55,6 @@ class EmbeddedRelationalPersistentEntity<T> implements RelationalPersistentEntit @@ -56,11 +55,6 @@ class EmbeddedRelationalPersistentEntity<T> implements RelationalPersistentEntit
throw new MappingException("Embedded entity does not have an id column");
}
@Override
public Optional<SqlIdentifier> getIdSequence() {
return Optional.empty();
}
@Override
public void addPersistentProperty(RelationalPersistentProperty property) {
throw new UnsupportedOperationException();

6
spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/EmbeddedRelationalPersistentProperty.java

@ -105,6 +105,12 @@ class EmbeddedRelationalPersistentProperty implements RelationalPersistentProper @@ -105,6 +105,12 @@ class EmbeddedRelationalPersistentProperty implements RelationalPersistentProper
return delegate.isInsertOnly();
}
@Nullable
@Override
public SqlIdentifier getSequence() {
return delegate.getSequence();
}
@Override
public String getName() {
return delegate.getName();

8
spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/RelationalPersistentEntity.java

@ -15,8 +15,6 @@ @@ -15,8 +15,6 @@
*/
package org.springframework.data.relational.core.mapping;
import java.util.Optional;
import org.springframework.data.mapping.model.MutablePersistentEntity;
import org.springframework.data.relational.core.sql.SqlIdentifier;
@ -55,10 +53,4 @@ public interface RelationalPersistentEntity<T> extends MutablePersistentEntity<T @@ -55,10 +53,4 @@ public interface RelationalPersistentEntity<T> extends MutablePersistentEntity<T
*/
SqlIdentifier getIdColumn();
/**
* @return the target sequence that should be used for id generation
* @since 3.5
*/
Optional<SqlIdentifier> getIdSequence();
}

17
spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/RelationalPersistentProperty.java

@ -25,6 +25,7 @@ import org.springframework.lang.Nullable; @@ -25,6 +25,7 @@ import org.springframework.lang.Nullable;
* @author Jens Schauder
* @author Oliver Gierke
* @author Bastian Wilhelm
* @author Mark Paluch
*/
public interface RelationalPersistentProperty extends PersistentProperty<RelationalPersistentProperty> {
@ -94,4 +95,20 @@ public interface RelationalPersistentProperty extends PersistentProperty<Relatio @@ -94,4 +95,20 @@ public interface RelationalPersistentProperty extends PersistentProperty<Relatio
* @since 3.0
*/
boolean isInsertOnly();
/**
* @return the target sequence that should be used for value generation.
* @since 3.5
*/
@Nullable
SqlIdentifier getSequence();
/**
* @return {@literal true} if the property is associated with a sequence; {@literal false} otherwise.
* @since 3.5
*/
default boolean hasSequence() {
return getSequence() != null;
}
}

56
spring-data-relational/src/test/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentEntityUnitTests.java

@ -58,42 +58,6 @@ class BasicRelationalPersistentEntityUnitTests { @@ -58,42 +58,6 @@ class BasicRelationalPersistentEntityUnitTests {
assertThat(entity.getTableName()).isEqualTo(quoted("dummy_sub_entity"));
}
@Test // GH-1923
void entityWithNoSequence() {
RelationalPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(DummySubEntity.class);
assertThat(entity.getIdSequence()).isEmpty();
}
@Test // GH-1923
void determineSequenceName() {
RelationalPersistentEntity<?> persistentEntity = mappingContext
.getRequiredPersistentEntity(EntityWithSequence.class);
assertThat(persistentEntity.getIdSequence()).contains(SqlIdentifier.quoted("my_seq"));
}
@Test // GH-1923
void determineSequenceNameFromValue() {
RelationalPersistentEntity<?> persistentEntity = mappingContext
.getRequiredPersistentEntity(EntityWithSequenceValueAlias.class);
assertThat(persistentEntity.getIdSequence()).contains(SqlIdentifier.quoted("my_seq"));
}
@Test // GH-1923
void determineSequenceNameWithSchemaSpecified() {
RelationalPersistentEntity<?> persistentEntity = mappingContext
.getRequiredPersistentEntity(EntityWithSequenceAndSchema.class);
assertThat(persistentEntity.getIdSequence())
.contains(SqlIdentifier.from(SqlIdentifier.quoted("public"), SqlIdentifier.quoted("my_seq")));
}
@Test // DATAJDBC-294
void considerIdColumnName() {
@ -239,26 +203,6 @@ class BasicRelationalPersistentEntityUnitTests { @@ -239,26 +203,6 @@ class BasicRelationalPersistentEntityUnitTests {
@Column("renamedId") Long id;
}
@Table("entity_with_sequence")
static class EntityWithSequence {
@Id
@Sequence(sequence = "my_seq") Long id;
}
@Table("entity_with_sequence_value_alias")
static class EntityWithSequenceValueAlias {
@Id
@Column("myId")
@Sequence(value = "my_seq") Long id;
}
@Table("entity_with_sequence_and_schema")
static class EntityWithSequenceAndSchema {
@Id
@Column("myId")
@Sequence(sequence = "my_seq", schema = "public") Long id;
}
@Table()
static class DummyEntityWithEmptyAnnotation {
@Id

207
spring-data-relational/src/test/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentPropertyUnitTests.java

@ -31,6 +31,7 @@ import org.junit.jupiter.api.Test; @@ -31,6 +31,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.data.annotation.Id;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.relational.core.mapping.Embedded.OnEmpty;
import org.springframework.data.relational.core.sql.SqlIdentifier;
/**
* Unit tests for the {@link BasicRelationalPersistentProperty}.
@ -40,14 +41,15 @@ import org.springframework.data.relational.core.mapping.Embedded.OnEmpty; @@ -40,14 +41,15 @@ import org.springframework.data.relational.core.mapping.Embedded.OnEmpty;
* @author Florian Lüdiger
* @author Bastian Wilhelm
* @author Kurt Niemi
* @author Mark Paluch
*/
public class BasicRelationalPersistentPropertyUnitTests {
class BasicRelationalPersistentPropertyUnitTests {
RelationalMappingContext context = new RelationalMappingContext();
RelationalPersistentEntity<?> entity = context.getRequiredPersistentEntity(DummyEntity.class);
private RelationalMappingContext context = new RelationalMappingContext();
private RelationalPersistentEntity<?> entity = context.getRequiredPersistentEntity(DummyEntity.class);
@Test // DATAJDBC-106
public void detectsAnnotatedColumnName() {
void detectsAnnotatedColumnName() {
assertThat(entity.getRequiredPersistentProperty("name").getColumnName()).isEqualTo(quoted("dummy_name"));
assertThat(entity.getRequiredPersistentProperty("localDateTime").getColumnName())
@ -55,7 +57,7 @@ public class BasicRelationalPersistentPropertyUnitTests { @@ -55,7 +57,7 @@ public class BasicRelationalPersistentPropertyUnitTests {
}
@Test // DATAJDBC-218
public void detectsAnnotatedColumnAndKeyName() {
void detectsAnnotatedColumnAndKeyName() {
RelationalPersistentProperty listProperty = entity.getRequiredPersistentProperty("someList");
@ -91,7 +93,7 @@ public class BasicRelationalPersistentPropertyUnitTests { @@ -91,7 +93,7 @@ public class BasicRelationalPersistentPropertyUnitTests {
}
@Test // DATAJDBC-111
public void detectsEmbeddedEntity() {
void detectsEmbeddedEntity() {
final RelationalPersistentEntity<?> requiredPersistentEntity = context
.getRequiredPersistentEntity(DummyEntity.class);
@ -120,7 +122,7 @@ public class BasicRelationalPersistentPropertyUnitTests { @@ -120,7 +122,7 @@ public class BasicRelationalPersistentPropertyUnitTests {
}
@Test // DATAJDBC-259
public void classificationOfCollectionLikeProperties() {
void classificationOfCollectionLikeProperties() {
RelationalPersistentProperty listOfString = entity.getRequiredPersistentProperty("listOfString");
RelationalPersistentProperty arrayOfString = entity.getRequiredPersistentProperty("arrayOfString");
@ -150,11 +152,45 @@ public class BasicRelationalPersistentPropertyUnitTests { @@ -150,11 +152,45 @@ public class BasicRelationalPersistentPropertyUnitTests {
softly.assertAll();
}
@Test // GH-1923
void entityWithNoSequence() {
RelationalPersistentEntity<?> entity = context.getRequiredPersistentEntity(DummyEntity.class);
assertThat(entity.getRequiredIdProperty().getSequence()).isNull();
}
@Test // GH-1923
void determineSequenceName() {
RelationalPersistentEntity<?> persistentEntity = context.getRequiredPersistentEntity(EntityWithSequence.class);
assertThat(persistentEntity.getRequiredIdProperty().getSequence()).isEqualTo(SqlIdentifier.quoted("my_seq"));
}
@Test // GH-1923
void determineSequenceNameFromValue() {
RelationalPersistentEntity<?> persistentEntity = context
.getRequiredPersistentEntity(EntityWithSequenceValueAlias.class);
assertThat(persistentEntity.getRequiredIdProperty().getSequence()).isEqualTo(SqlIdentifier.quoted("my_seq"));
}
@Test // GH-1923
void determineSequenceNameWithSchemaSpecified() {
RelationalPersistentEntity<?> persistentEntity = context
.getRequiredPersistentEntity(EntityWithSequenceAndSchema.class);
assertThat(persistentEntity.getRequiredIdProperty().getSequence())
.isEqualTo(SqlIdentifier.from(SqlIdentifier.quoted("public"), SqlIdentifier.quoted("my_seq")));
}
@SuppressWarnings("unused")
private static class DummyEntity {
static class DummyEntity {
@Id
private final Long id;
@Id private final Long id;
private final SomeEnum someEnum;
private final LocalDateTime localDateTime;
private final ZonedDateTime zonedDateTime;
@ -166,8 +202,7 @@ public class BasicRelationalPersistentPropertyUnitTests { @@ -166,8 +202,7 @@ public class BasicRelationalPersistentPropertyUnitTests {
private final OtherEntity[] arrayOfEntity;
@MappedCollection(idColumn = "dummy_column_name",
keyColumn = "dummy_key_column_name")
private List<Integer> someList;
keyColumn = "dummy_key_column_name") private List<Integer> someList;
// DATACMNS-106
private @Column("dummy_name") String name;
@ -177,17 +212,14 @@ public class BasicRelationalPersistentPropertyUnitTests { @@ -177,17 +212,14 @@ public class BasicRelationalPersistentPropertyUnitTests {
public static String littleBobbyTablesValue = "--; DROP ALL TABLES;--";
@Column(value = "#{T(org.springframework.data.relational.core.mapping."
+ "BasicRelationalPersistentPropertyUnitTests$DummyEntity"
+ ").spelExpression1Value}")
private String spelExpression1;
+ ").spelExpression1Value}") private String spelExpression1;
@Column(value = "#{T(org.springframework.data.relational.core.mapping."
+ "BasicRelationalPersistentPropertyUnitTests$DummyEntity"
+ ").littleBobbyTablesValue}")
private String littleBobbyTables;
+ ").littleBobbyTablesValue}") private String littleBobbyTables;
@Column(
value = "--; DROP ALL TABLES;--")
private String poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot;
value = "--; DROP ALL TABLES;--") private String poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot;
// DATAJDBC-111
private @Embedded(onEmpty = OnEmpty.USE_NULL) EmbeddableEntity embeddableEntity;
@ -195,7 +227,9 @@ public class BasicRelationalPersistentPropertyUnitTests { @@ -195,7 +227,9 @@ public class BasicRelationalPersistentPropertyUnitTests {
// DATAJDBC-111
private @Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "prefix") EmbeddableEntity prefixedEmbeddableEntity;
public DummyEntity(Long id, SomeEnum someEnum, LocalDateTime localDateTime, ZonedDateTime zonedDateTime, List<String> listOfString, String[] arrayOfString, List<OtherEntity> listOfEntity, OtherEntity[] arrayOfEntity) {
public DummyEntity(Long id, SomeEnum someEnum, LocalDateTime localDateTime, ZonedDateTime zonedDateTime,
List<String> listOfString, String[] arrayOfString, List<OtherEntity> listOfEntity,
OtherEntity[] arrayOfEntity) {
this.id = id;
this.someEnum = someEnum;
this.localDateTime = localDateTime;
@ -219,59 +253,59 @@ public class BasicRelationalPersistentPropertyUnitTests { @@ -219,59 +253,59 @@ public class BasicRelationalPersistentPropertyUnitTests {
return null;
}
public Long getId() {
Long getId() {
return this.id;
}
public SomeEnum getSomeEnum() {
SomeEnum getSomeEnum() {
return this.someEnum;
}
public ZonedDateTime getZonedDateTime() {
ZonedDateTime getZonedDateTime() {
return this.zonedDateTime;
}
public List<String> getListOfString() {
List<String> getListOfString() {
return this.listOfString;
}
public String[] getArrayOfString() {
String[] getArrayOfString() {
return this.arrayOfString;
}
public List<OtherEntity> getListOfEntity() {
List<OtherEntity> getListOfEntity() {
return this.listOfEntity;
}
public OtherEntity[] getArrayOfEntity() {
OtherEntity[] getArrayOfEntity() {
return this.arrayOfEntity;
}
public List<Integer> getSomeList() {
List<Integer> getSomeList() {
return this.someList;
}
public String getName() {
String getName() {
return this.name;
}
public String getSpelExpression1() {
String getSpelExpression1() {
return this.spelExpression1;
}
public String getLittleBobbyTables() {
String getLittleBobbyTables() {
return this.littleBobbyTables;
}
public String getPoorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot() {
String getPoorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot() {
return this.poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot;
}
public EmbeddableEntity getEmbeddableEntity() {
EmbeddableEntity getEmbeddableEntity() {
return this.embeddableEntity;
}
public EmbeddableEntity getPrefixedEmbeddableEntity() {
EmbeddableEntity getPrefixedEmbeddableEntity() {
return this.prefixedEmbeddableEntity;
}
@ -291,7 +325,8 @@ public class BasicRelationalPersistentPropertyUnitTests { @@ -291,7 +325,8 @@ public class BasicRelationalPersistentPropertyUnitTests {
this.littleBobbyTables = littleBobbyTables;
}
public void setPoorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot(String poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot) {
public void setPoorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot(
String poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot) {
this.poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot = poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot;
}
@ -304,16 +339,21 @@ public class BasicRelationalPersistentPropertyUnitTests { @@ -304,16 +339,21 @@ public class BasicRelationalPersistentPropertyUnitTests {
}
public boolean equals(final Object o) {
if (o == this) return true;
if (!(o instanceof DummyEntity)) return false;
if (o == this)
return true;
if (!(o instanceof DummyEntity))
return false;
final DummyEntity other = (DummyEntity) o;
if (!other.canEqual((Object) this)) return false;
if (!other.canEqual((Object) this))
return false;
final Object this$id = this.getId();
final Object other$id = other.getId();
if (this$id == null ? other$id != null : !this$id.equals(other$id)) return false;
if (this$id == null ? other$id != null : !this$id.equals(other$id))
return false;
final Object this$someEnum = this.getSomeEnum();
final Object other$someEnum = other.getSomeEnum();
if (this$someEnum == null ? other$someEnum != null : !this$someEnum.equals(other$someEnum)) return false;
if (this$someEnum == null ? other$someEnum != null : !this$someEnum.equals(other$someEnum))
return false;
final Object this$localDateTime = this.getLocalDateTime();
final Object other$localDateTime = other.getLocalDateTime();
if (this$localDateTime == null ? other$localDateTime != null : !this$localDateTime.equals(other$localDateTime))
@ -326,42 +366,55 @@ public class BasicRelationalPersistentPropertyUnitTests { @@ -326,42 +366,55 @@ public class BasicRelationalPersistentPropertyUnitTests {
final Object other$listOfString = other.getListOfString();
if (this$listOfString == null ? other$listOfString != null : !this$listOfString.equals(other$listOfString))
return false;
if (!java.util.Arrays.deepEquals(this.getArrayOfString(), other.getArrayOfString())) return false;
if (!java.util.Arrays.deepEquals(this.getArrayOfString(), other.getArrayOfString()))
return false;
final Object this$listOfEntity = this.getListOfEntity();
final Object other$listOfEntity = other.getListOfEntity();
if (this$listOfEntity == null ? other$listOfEntity != null : !this$listOfEntity.equals(other$listOfEntity))
return false;
if (!java.util.Arrays.deepEquals(this.getArrayOfEntity(), other.getArrayOfEntity())) return false;
if (!java.util.Arrays.deepEquals(this.getArrayOfEntity(), other.getArrayOfEntity()))
return false;
final Object this$someList = this.getSomeList();
final Object other$someList = other.getSomeList();
if (this$someList == null ? other$someList != null : !this$someList.equals(other$someList)) return false;
if (this$someList == null ? other$someList != null : !this$someList.equals(other$someList))
return false;
final Object this$name = this.getName();
final Object other$name = other.getName();
if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;
if (this$name == null ? other$name != null : !this$name.equals(other$name))
return false;
final Object this$spelExpression1 = this.getSpelExpression1();
final Object other$spelExpression1 = other.getSpelExpression1();
if (this$spelExpression1 == null ? other$spelExpression1 != null : !this$spelExpression1.equals(other$spelExpression1))
if (this$spelExpression1 == null ? other$spelExpression1 != null
: !this$spelExpression1.equals(other$spelExpression1))
return false;
final Object this$littleBobbyTables = this.getLittleBobbyTables();
final Object other$littleBobbyTables = other.getLittleBobbyTables();
if (this$littleBobbyTables == null ? other$littleBobbyTables != null : !this$littleBobbyTables.equals(other$littleBobbyTables))
if (this$littleBobbyTables == null ? other$littleBobbyTables != null
: !this$littleBobbyTables.equals(other$littleBobbyTables))
return false;
final Object this$poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot = this.getPoorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot();
final Object other$poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot = other.getPoorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot();
if (this$poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot == null ? other$poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot != null : !this$poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot.equals(other$poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot))
final Object this$poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot = this
.getPoorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot();
final Object other$poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot = other
.getPoorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot();
if (this$poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot == null
? other$poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot != null
: !this$poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot
.equals(other$poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot))
return false;
final Object this$embeddableEntity = this.getEmbeddableEntity();
final Object other$embeddableEntity = other.getEmbeddableEntity();
if (this$embeddableEntity == null ? other$embeddableEntity != null : !this$embeddableEntity.equals(other$embeddableEntity))
if (this$embeddableEntity == null ? other$embeddableEntity != null
: !this$embeddableEntity.equals(other$embeddableEntity))
return false;
final Object this$prefixedEmbeddableEntity = this.getPrefixedEmbeddableEntity();
final Object other$prefixedEmbeddableEntity = other.getPrefixedEmbeddableEntity();
if (this$prefixedEmbeddableEntity == null ? other$prefixedEmbeddableEntity != null : !this$prefixedEmbeddableEntity.equals(other$prefixedEmbeddableEntity))
if (this$prefixedEmbeddableEntity == null ? other$prefixedEmbeddableEntity != null
: !this$prefixedEmbeddableEntity.equals(other$prefixedEmbeddableEntity))
return false;
return true;
}
protected boolean canEqual(final Object other) {
boolean canEqual(final Object other) {
return other instanceof DummyEntity;
}
@ -390,8 +443,10 @@ public class BasicRelationalPersistentPropertyUnitTests { @@ -390,8 +443,10 @@ public class BasicRelationalPersistentPropertyUnitTests {
result = result * PRIME + ($spelExpression1 == null ? 43 : $spelExpression1.hashCode());
final Object $littleBobbyTables = this.getLittleBobbyTables();
result = result * PRIME + ($littleBobbyTables == null ? 43 : $littleBobbyTables.hashCode());
final Object $poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot = this.getPoorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot();
result = result * PRIME + ($poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot == null ? 43 : $poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot.hashCode());
final Object $poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot = this
.getPoorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot();
result = result * PRIME + ($poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot == null ? 43
: $poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot.hashCode());
final Object $embeddableEntity = this.getEmbeddableEntity();
result = result * PRIME + ($embeddableEntity == null ? 43 : $embeddableEntity.hashCode());
final Object $prefixedEmbeddableEntity = this.getPrefixedEmbeddableEntity();
@ -400,11 +455,20 @@ public class BasicRelationalPersistentPropertyUnitTests { @@ -400,11 +455,20 @@ public class BasicRelationalPersistentPropertyUnitTests {
}
public String toString() {
return "BasicRelationalPersistentPropertyUnitTests.DummyEntity(id=" + this.getId() + ", someEnum=" + this.getSomeEnum() + ", localDateTime=" + this.getLocalDateTime() + ", zonedDateTime=" + this.getZonedDateTime() + ", listOfString=" + this.getListOfString() + ", arrayOfString=" + java.util.Arrays.deepToString(this.getArrayOfString()) + ", listOfEntity=" + this.getListOfEntity() + ", arrayOfEntity=" + java.util.Arrays.deepToString(this.getArrayOfEntity()) + ", someList=" + this.getSomeList() + ", name=" + this.getName() + ", spelExpression1=" + this.getSpelExpression1() + ", littleBobbyTables=" + this.getLittleBobbyTables() + ", poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot=" + this.getPoorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot() + ", embeddableEntity=" + this.getEmbeddableEntity() + ", prefixedEmbeddableEntity=" + this.getPrefixedEmbeddableEntity() + ")";
return "BasicRelationalPersistentPropertyUnitTests.DummyEntity(id=" + this.getId() + ", someEnum="
+ this.getSomeEnum() + ", localDateTime=" + this.getLocalDateTime() + ", zonedDateTime="
+ this.getZonedDateTime() + ", listOfString=" + this.getListOfString() + ", arrayOfString="
+ java.util.Arrays.deepToString(this.getArrayOfString()) + ", listOfEntity=" + this.getListOfEntity()
+ ", arrayOfEntity=" + java.util.Arrays.deepToString(this.getArrayOfEntity()) + ", someList="
+ this.getSomeList() + ", name=" + this.getName() + ", spelExpression1=" + this.getSpelExpression1()
+ ", littleBobbyTables=" + this.getLittleBobbyTables()
+ ", poorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot="
+ this.getPoorDeveloperProgrammaticallyAskingToShootThemselvesInTheFoot() + ", embeddableEntity="
+ this.getEmbeddableEntity() + ", prefixedEmbeddableEntity=" + this.getPrefixedEmbeddableEntity() + ")";
}
}
static class WithMappedCollection {
private static class WithMappedCollection {
@MappedCollection(idColumn = "#{'id_col'}", keyColumn = "#{'key_col'}") private List<Integer> someList;
}
@ -422,15 +486,18 @@ public class BasicRelationalPersistentPropertyUnitTests { @@ -422,15 +486,18 @@ public class BasicRelationalPersistentPropertyUnitTests {
this.embeddedTest = embeddedTest;
}
public String getEmbeddedTest() {
String getEmbeddedTest() {
return this.embeddedTest;
}
public boolean equals(final Object o) {
if (o == this) return true;
if (!(o instanceof EmbeddableEntity)) return false;
if (o == this)
return true;
if (!(o instanceof EmbeddableEntity))
return false;
final EmbeddableEntity other = (EmbeddableEntity) o;
if (!other.canEqual((Object) this)) return false;
if (!other.canEqual((Object) this))
return false;
final Object this$embeddedTest = this.getEmbeddedTest();
final Object other$embeddedTest = other.getEmbeddedTest();
if (this$embeddedTest == null ? other$embeddedTest != null : !this$embeddedTest.equals(other$embeddedTest))
@ -438,7 +505,7 @@ public class BasicRelationalPersistentPropertyUnitTests { @@ -438,7 +505,7 @@ public class BasicRelationalPersistentPropertyUnitTests {
return true;
}
protected boolean canEqual(final Object other) {
boolean canEqual(final Object other) {
return other instanceof EmbeddableEntity;
}
@ -457,4 +524,24 @@ public class BasicRelationalPersistentPropertyUnitTests { @@ -457,4 +524,24 @@ public class BasicRelationalPersistentPropertyUnitTests {
@SuppressWarnings("unused")
private static class OtherEntity {}
@Table("entity_with_sequence")
static class EntityWithSequence {
@Id
@Sequence(sequence = "my_seq") Long id;
}
@Table("entity_with_sequence_value_alias")
static class EntityWithSequenceValueAlias {
@Id
@Column("myId")
@Sequence(value = "my_seq") Long id;
}
@Table("entity_with_sequence_and_schema")
static class EntityWithSequenceAndSchema {
@Id
@Column("myId")
@Sequence(sequence = "my_seq", schema = "public") Long id;
}
}

Loading…
Cancel
Save