Skip to content

Commit 8c017fc

Browse files
committed
Polishing.
Reference issues in tests comments. Removed `DisabledOnDatabase` IdGeneration default methods related to sequence generation are now internally consistent. Formatting and naming. IdGeneration offers simple support by default. Fix exception in oracle integration test setup Use SqlIdentifier for sequence names Remove SEQUENCE id source Added documentation See #1923 Original pull request #1955
1 parent d1c9960 commit 8c017fc

26 files changed

+250
-290
lines changed

pom.xml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
34

45
<modelVersion>4.0.0</modelVersion>
56

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

+7-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
1212
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
1313
import org.springframework.data.relational.core.mapping.event.BeforeSaveCallback;
14+
import org.springframework.data.relational.core.sql.SqlIdentifier;
1415
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
1516
import org.springframework.util.Assert;
1617

@@ -40,23 +41,25 @@ public IdGeneratingBeforeSaveCallback(
4041

4142
@Override
4243
public Object onBeforeSave(Object aggregate, MutableAggregateChange<Object> aggregateChange) {
44+
4345
Assert.notNull(aggregate, "The aggregate cannot be null at this point");
46+
4447
RelationalPersistentEntity<?> persistentEntity = relationalMappingContext.getPersistentEntity(aggregate.getClass());
45-
Optional<String> idTargetSequence = persistentEntity.getIdTargetSequence();
48+
Optional<SqlIdentifier> idSequence = persistentEntity.getIdSequence();
4649

4750
if (dialect.getIdGeneration().sequencesSupported()) {
4851

4952
if (persistentEntity.getIdProperty() != null) {
50-
idTargetSequence
51-
.map(s -> dialect.getIdGeneration().nextValueFromSequenceSelect(s))
53+
idSequence
54+
.map(s -> dialect.getIdGeneration().createSequenceQuery(s))
5255
.ifPresent(sql -> {
5356
Long idValue = operations.queryForObject(sql, Map.of(), (rs, rowNum) -> rs.getLong(1));
5457
PersistentPropertyAccessor<Object> propertyAccessor = persistentEntity.getPropertyAccessor(aggregate);
5558
propertyAccessor.setProperty(persistentEntity.getRequiredIdProperty(), idValue);
5659
});
5760
}
5861
} else {
59-
if (idTargetSequence.isPresent()) {
62+
if (idSequence.isPresent()) {
6063
LOG.warn("""
6164
It seems you're trying to insert an aggregate of type '%s' annotated with @TargetSequence, but the problem is RDBMS you're
6265
working with does not support sequences as such. Falling back to identity columns

spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/mapping/IdGeneratingBeforeSaveCallbackTest.java

+13-23
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import org.springframework.data.relational.core.dialect.PostgresDialect;
1515
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
1616
import org.springframework.data.relational.core.mapping.Table;
17-
import org.springframework.data.relational.core.mapping.TargetSequence;
17+
import org.springframework.data.relational.core.mapping.Sequence;
1818
import org.springframework.data.relational.core.sql.IdentifierProcessing;
1919
import org.springframework.jdbc.core.RowMapper;
2020
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
@@ -26,68 +26,58 @@
2626
*/
2727
class IdGeneratingBeforeSaveCallbackTest {
2828

29-
@Test
30-
void test_mySqlDialect_sequenceGenerationIsNotSupported() {
31-
// given
32-
RelationalMappingContext relationalMappingContext = new RelationalMappingContext();
29+
@Test // GH-1923
30+
void mySqlDialectsequenceGenerationIsNotSupported() {
31+
32+
RelationalMappingContext relationalMappingContext = new RelationalMappingContext();
3333
MySqlDialect mySqlDialect = new MySqlDialect(IdentifierProcessing.NONE);
3434
NamedParameterJdbcOperations operations = mock(NamedParameterJdbcOperations.class);
3535

36-
// and
3736
IdGeneratingBeforeSaveCallback subject = new IdGeneratingBeforeSaveCallback(relationalMappingContext, mySqlDialect, operations);
3837

3938
NoSequenceEntity entity = new NoSequenceEntity();
4039

41-
// when
4240
Object processed = subject.onBeforeSave(entity, MutableAggregateChange.forSave(entity));
4341

44-
// then
4542
Assertions.assertThat(processed).isSameAs(entity);
4643
Assertions.assertThat(processed).usingRecursiveComparison().isEqualTo(entity);
4744
}
4845

49-
@Test
50-
void test_EntityIsNotMarkedWithTargetSequence() {
51-
// given
52-
RelationalMappingContext relationalMappingContext = new RelationalMappingContext();
46+
@Test // GH-1923
47+
void entityIsNotMarkedWithTargetSequence() {
48+
49+
RelationalMappingContext relationalMappingContext = new RelationalMappingContext();
5350
PostgresDialect mySqlDialect = PostgresDialect.INSTANCE;
5451
NamedParameterJdbcOperations operations = mock(NamedParameterJdbcOperations.class);
5552

56-
// and
5753
IdGeneratingBeforeSaveCallback subject = new IdGeneratingBeforeSaveCallback(relationalMappingContext, mySqlDialect, operations);
5854

5955
NoSequenceEntity entity = new NoSequenceEntity();
6056

61-
// when
6257
Object processed = subject.onBeforeSave(entity, MutableAggregateChange.forSave(entity));
6358

64-
// then
6559
Assertions.assertThat(processed).isSameAs(entity);
6660
Assertions.assertThat(processed).usingRecursiveComparison().isEqualTo(entity);
6761
}
6862

69-
@Test
70-
void test_EntityIdIsPopulatedFromSequence() {
71-
// given
63+
@Test // GH-1923
64+
void entityIdIsPopulatedFromSequence() {
65+
7266
RelationalMappingContext relationalMappingContext = new RelationalMappingContext();
7367
relationalMappingContext.getRequiredPersistentEntity(EntityWithSequence.class);
7468

7569
PostgresDialect mySqlDialect = PostgresDialect.INSTANCE;
7670
NamedParameterJdbcOperations operations = mock(NamedParameterJdbcOperations.class);
7771

78-
// and
7972
long generatedId = 112L;
8073
when(operations.queryForObject(anyString(), anyMap(), any(RowMapper.class))).thenReturn(generatedId);
8174

82-
// and
8375
IdGeneratingBeforeSaveCallback subject = new IdGeneratingBeforeSaveCallback(relationalMappingContext, mySqlDialect, operations);
8476

8577
EntityWithSequence entity = new EntityWithSequence();
8678

87-
// when
8879
Object processed = subject.onBeforeSave(entity, MutableAggregateChange.forSave(entity));
8980

90-
// then
9181
Assertions.assertThat(processed).isSameAs(entity);
9282
Assertions
9383
.assertThat(processed)
@@ -109,7 +99,7 @@ static class NoSequenceEntity {
10999
static class EntityWithSequence {
110100

111101
@Id
112-
@TargetSequence(value = "id_seq", schema = "public")
102+
@Sequence(value = "id_seq", schema = "public")
113103
private Long id;
114104

115105
private Long name;

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

+6-4
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
import org.springframework.data.relational.core.mapping.Column;
6666
import org.springframework.data.relational.core.mapping.MappedCollection;
6767
import org.springframework.data.relational.core.mapping.Table;
68-
import org.springframework.data.relational.core.mapping.TargetSequence;
68+
import org.springframework.data.relational.core.mapping.Sequence;
6969
import org.springframework.data.relational.core.mapping.event.AbstractRelationalEvent;
7070
import org.springframework.data.relational.core.mapping.event.AfterConvertEvent;
7171
import org.springframework.data.relational.core.sql.LockMode;
@@ -126,9 +126,10 @@ public void savesAnEntity() {
126126
"id_Prop = " + entity.getIdProp())).isEqualTo(1);
127127
}
128128

129-
@Test
129+
@Test // GH-1923
130130
@EnabledOnFeature(value = TestDatabaseFeatures.Feature.SUPPORTS_SEQUENCES)
131131
public void saveEntityWithTargetSequenceSpecified() {
132+
132133
EntityWithSequence first = entityWithSequenceRepository.save(new EntityWithSequence("first"));
133134
EntityWithSequence second = entityWithSequenceRepository.save(new EntityWithSequence("second"));
134135

@@ -139,9 +140,10 @@ public void saveEntityWithTargetSequenceSpecified() {
139140
assertThat(second.getName()).isEqualTo("second");
140141
}
141142

142-
@Test
143+
@Test // GH-1923
143144
@EnabledOnFeature(value = TestDatabaseFeatures.Feature.SUPPORTS_SEQUENCES)
144145
public void batchInsertEntityWithTargetSequenceSpecified() {
146+
145147
Iterable<EntityWithSequence> results = entityWithSequenceRepository
146148
.saveAll(List.of(new EntityWithSequence("first"), new EntityWithSequence("second")));
147149

@@ -1862,7 +1864,7 @@ private static DummyEntity createEntity(String entityName, Consumer<DummyEntity>
18621864
static class EntityWithSequence {
18631865

18641866
@Id
1865-
@TargetSequence(sequence = "entity_sequence") private Long id;
1867+
@Sequence(sequence = "ENTITY_SEQUENCE") private Long id;
18661868

18671869
private String name;
18681870

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

-27
This file was deleted.

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

-36
This file was deleted.

spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.repository/JdbcRepositoryIntegrationTests-mariadb.sql

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,4 @@ CREATE TABLE ENTITY_WITH_SEQUENCE
4747
NAME VARCHAR(100)
4848
);
4949

50-
CREATE SEQUENCE ENTITY_SEQUENCE START WITH 1 INCREMENT BY 1 NO MAXVALUE;
50+
CREATE SEQUENCE `ENTITY_SEQUENCE` START WITH 1 INCREMENT BY 1 NO MAXVALUE;

spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.repository/JdbcRepositoryIntegrationTests-oracle.sql

+3-3
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ CREATE TABLE WITH_DELIMITED_COLUMN
4747
ID NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY PRIMARY KEY,
4848
"ORG.XTUNIT.IDENTIFIER" VARCHAR(100),
4949
STYPE VARCHAR(100)
50-
)
50+
);
5151

5252
CREATE TABLE ENTITY_WITH_SEQUENCE
5353
(
54-
ID BIGINT,
54+
ID NUMBER,
5555
NAME VARCHAR(100)
5656
);
5757

58-
CREATE SEQUENCE ENTITY_SEQUENCE START WITH 1 INCREMENT BY 1 NO MAXVALUE;
58+
CREATE SEQUENCE ENTITY_SEQUENCE START WITH 1 INCREMENT BY 1;

spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.repository/JdbcRepositoryIntegrationTests-postgres.sql

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,4 @@ CREATE TABLE ENTITY_WITH_SEQUENCE
5555
NAME VARCHAR(100)
5656
);
5757

58-
CREATE SEQUENCE ENTITY_SEQUENCE START WITH 1 INCREMENT BY 1 NO MAXVALUE;
58+
CREATE SEQUENCE "ENTITY_SEQUENCE" START WITH 1 INCREMENT BY 1 NO MAXVALUE;

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

+3-11
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
*/
1616
package org.springframework.data.relational.core.conversion;
1717

18-
import java.util.Optional;
19-
2018
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
2119
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
2220

@@ -42,12 +40,7 @@ public enum IdValueSource {
4240
/**
4341
* There is no id property, and therefore no id value source.
4442
*/
45-
NONE,
46-
47-
/**
48-
* The id should be dervied from the database sequence
49-
*/
50-
SEQUENCE;
43+
NONE;
5144

5245
/**
5346
* Returns the appropriate {@link IdValueSource} for the instance: {@link IdValueSource#NONE} when the entity has no
@@ -56,9 +49,8 @@ public enum IdValueSource {
5649
*/
5750
public static <T> IdValueSource forInstance(Object instance, RelationalPersistentEntity<T> persistentEntity) {
5851

59-
Optional<String> idTargetSequence = persistentEntity.getIdTargetSequence();
60-
if (idTargetSequence.isPresent()) {
61-
return IdValueSource.SEQUENCE;
52+
if (persistentEntity.getIdSequence().isPresent()) {
53+
return IdValueSource.PROVIDED;
6254
}
6355

6456
Object idValue = persistentEntity.getIdentifierAccessor(instance).getIdentifier();

spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/Db2Dialect.java

+14-13
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
import java.util.Collection;
1919
import java.util.Collections;
2020

21-
import org.springframework.data.relational.core.sql.IdentifierProcessing;
2221
import org.springframework.data.relational.core.sql.LockOptions;
22+
import org.springframework.data.relational.core.sql.SqlIdentifier;
2323

2424
/**
2525
* An SQL dialect for DB2.
@@ -41,14 +41,20 @@ public boolean supportedForBatchOperations() {
4141
return false;
4242
}
4343

44-
/**
45-
* This workaround (non-ANSI SQL way of querying sequence) exists for the same reasons it exists for {@link HsqlDbDialect}
46-
*
47-
* @see HsqlDbDialect#getIdGeneration()#nextValueFromSequenceSelect(String)
48-
*/
4944
@Override
50-
public String nextValueFromSequenceSelect(String sequenceName) {
51-
return "SELECT NEXT VALUE FOR %s FROM SYSCAT.SEQUENCES LIMIT 1".formatted(sequenceName);
45+
public boolean sequencesSupported() {
46+
return true;
47+
}
48+
49+
@Override
50+
public String createSequenceQuery(SqlIdentifier sequenceName) {
51+
/*
52+
* This workaround (non-ANSI SQL way of querying sequence) exists for the same reasons it exists for {@link HsqlDbDialect}
53+
*
54+
* @see HsqlDbDialect#getIdGeneration()#nextValueFromSequenceSelect(String)
55+
*/
56+
return "SELECT NEXT VALUE FOR %s FROM SYSCAT.SEQUENCES LIMIT 1"
57+
.formatted(sequenceName.toSql(INSTANCE.getIdentifierProcessing()));
5258
}
5359
};
5460

@@ -104,11 +110,6 @@ public Position getClausePosition() {
104110
};
105111
}
106112

107-
@Override
108-
public IdentifierProcessing getIdentifierProcessing() {
109-
return IdentifierProcessing.ANSI;
110-
}
111-
112113
@Override
113114
public Collection<Object> getConverters() {
114115
return Collections.singletonList(TimestampAtUtcToOffsetDateTimeConverter.INSTANCE);

0 commit comments

Comments
 (0)