Skip to content

Commit 13673aa

Browse files
committed
GH-611 added JdbcExceptionTranslator
Signed-off-by: mipo256 <[email protected]>
1 parent 5c0ebf3 commit 13673aa

12 files changed

+166
-95
lines changed

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

+30-41
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,14 @@
1515
*/
1616
package org.springframework.data.jdbc.core;
1717

18-
import org.springframework.dao.OptimisticLockingFailureException;
18+
import java.util.List;
19+
1920
import org.springframework.data.jdbc.core.convert.DataAccessStrategy;
2021
import org.springframework.data.jdbc.core.convert.JdbcConverter;
2122
import org.springframework.data.relational.core.conversion.AggregateChange;
2223
import org.springframework.data.relational.core.conversion.DbAction;
23-
import org.springframework.data.relational.core.conversion.DbActionExecutionException;
2424
import org.springframework.data.relational.core.conversion.MutableAggregateChange;
2525

26-
import java.util.List;
27-
2826
/**
2927
* Executes an {@link MutableAggregateChange}.
3028
*
@@ -79,43 +77,34 @@ <T> void executeDelete(AggregateChange<T> aggregateChange) {
7977
}
8078

8179
private void execute(DbAction<?> action, JdbcAggregateChangeExecutionContext executionContext) {
82-
83-
try {
84-
if (action instanceof DbAction.InsertRoot<?> insertRoot) {
85-
executionContext.executeInsertRoot(insertRoot);
86-
} else if (action instanceof DbAction.BatchInsertRoot<?> batchInsertRoot) {
87-
executionContext.executeBatchInsertRoot(batchInsertRoot);
88-
} else if (action instanceof DbAction.Insert<?> insert) {
89-
executionContext.executeInsert(insert);
90-
} else if (action instanceof DbAction.BatchInsert<?> batchInsert) {
91-
executionContext.executeBatchInsert(batchInsert);
92-
} else if (action instanceof DbAction.UpdateRoot<?> updateRoot) {
93-
executionContext.executeUpdateRoot(updateRoot);
94-
} else if (action instanceof DbAction.Delete<?> delete) {
95-
executionContext.executeDelete(delete);
96-
} else if (action instanceof DbAction.BatchDelete<?> batchDelete) {
97-
executionContext.executeBatchDelete(batchDelete);
98-
} else if (action instanceof DbAction.DeleteAll<?> deleteAll) {
99-
executionContext.executeDeleteAll(deleteAll);
100-
} else if (action instanceof DbAction.DeleteRoot<?> deleteRoot) {
101-
executionContext.executeDeleteRoot(deleteRoot);
102-
} else if (action instanceof DbAction.BatchDeleteRoot<?> batchDeleteRoot) {
103-
executionContext.executeBatchDeleteRoot(batchDeleteRoot);
104-
} else if (action instanceof DbAction.DeleteAllRoot<?> deleteAllRoot) {
105-
executionContext.executeDeleteAllRoot(deleteAllRoot);
106-
} else if (action instanceof DbAction.AcquireLockRoot<?> acquireLockRoot) {
107-
executionContext.executeAcquireLock(acquireLockRoot);
108-
} else if (action instanceof DbAction.AcquireLockAllRoot<?> acquireLockAllRoot) {
109-
executionContext.executeAcquireLockAllRoot(acquireLockAllRoot);
110-
} else {
111-
throw new RuntimeException("unexpected action");
112-
}
113-
} catch (Exception e) {
114-
115-
if (e instanceof OptimisticLockingFailureException) {
116-
throw e;
117-
}
118-
throw new DbActionExecutionException(action, e);
80+
if (action instanceof DbAction.InsertRoot<?> insertRoot) {
81+
executionContext.executeInsertRoot(insertRoot);
82+
} else if (action instanceof DbAction.BatchInsertRoot<?> batchInsertRoot) {
83+
executionContext.executeBatchInsertRoot(batchInsertRoot);
84+
} else if (action instanceof DbAction.Insert<?> insert) {
85+
executionContext.executeInsert(insert);
86+
} else if (action instanceof DbAction.BatchInsert<?> batchInsert) {
87+
executionContext.executeBatchInsert(batchInsert);
88+
} else if (action instanceof DbAction.UpdateRoot<?> updateRoot) {
89+
executionContext.executeUpdateRoot(updateRoot);
90+
} else if (action instanceof DbAction.Delete<?> delete) {
91+
executionContext.executeDelete(delete);
92+
} else if (action instanceof DbAction.BatchDelete<?> batchDelete) {
93+
executionContext.executeBatchDelete(batchDelete);
94+
} else if (action instanceof DbAction.DeleteAll<?> deleteAll) {
95+
executionContext.executeDeleteAll(deleteAll);
96+
} else if (action instanceof DbAction.DeleteRoot<?> deleteRoot) {
97+
executionContext.executeDeleteRoot(deleteRoot);
98+
} else if (action instanceof DbAction.BatchDeleteRoot<?> batchDeleteRoot) {
99+
executionContext.executeBatchDeleteRoot(batchDeleteRoot);
100+
} else if (action instanceof DbAction.DeleteAllRoot<?> deleteAllRoot) {
101+
executionContext.executeDeleteAllRoot(deleteAllRoot);
102+
} else if (action instanceof DbAction.AcquireLockRoot<?> acquireLockRoot) {
103+
executionContext.executeAcquireLock(acquireLockRoot);
104+
} else if (action instanceof DbAction.AcquireLockAllRoot<?> acquireLockAllRoot) {
105+
executionContext.executeAcquireLockAllRoot(acquireLockAllRoot);
106+
} else {
107+
throw new RuntimeException("unexpected action");
119108
}
120109
}
121110
}

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

+3-4
Original file line numberDiff line numberDiff line change
@@ -563,9 +563,8 @@ void updateFailedRootDoesNotExist() {
563563
LegoSet entity = new LegoSet();
564564
entity.id = 100L; // does not exist in the database
565565

566-
assertThatExceptionOfType(DbActionExecutionException.class) //
567-
.isThrownBy(() -> template.save(entity)) //
568-
.withCauseInstanceOf(IncorrectUpdateSemanticsDataAccessException.class);
566+
assertThatExceptionOfType(IncorrectUpdateSemanticsDataAccessException.class) //
567+
.isThrownBy(() -> template.save(entity));
569568
}
570569

571570
@Test // DATAJDBC-112
@@ -1165,7 +1164,7 @@ void saveAndUpdateAggregateWithIdAndNullVersion() {
11651164
aggregate.setVersion(null);
11661165
aggregate.setId(23L);
11671166

1168-
assertThatThrownBy(() -> template.save(aggregate)).isInstanceOf(DbActionExecutionException.class);
1167+
assertThatThrownBy(() -> template.save(aggregate)).isInstanceOf(IncorrectUpdateSemanticsDataAccessException.class);
11691168
}
11701169

11711170
@Test // DATAJDBC-462

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

+75-6
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
*/
1616
package org.springframework.data.jdbc.repository;
1717

18-
import static java.util.Arrays.*;
19-
import static java.util.Collections.*;
20-
import static org.assertj.core.api.Assertions.*;
21-
import static org.assertj.core.api.SoftAssertions.*;
18+
import static java.util.Arrays.asList;
19+
import static java.util.Collections.emptyList;
20+
import static java.util.Collections.singletonList;
21+
import static org.assertj.core.api.Assertions.assertThat;
22+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
23+
import static org.assertj.core.api.SoftAssertions.assertSoftly;
2224

2325
import java.io.IOException;
2426
import java.sql.ResultSet;
@@ -37,6 +39,7 @@
3739
import java.util.function.Consumer;
3840
import java.util.stream.Stream;
3941

42+
import org.assertj.core.api.Assertions;
4043
import org.junit.jupiter.api.BeforeEach;
4144
import org.junit.jupiter.api.Test;
4245
import org.junit.jupiter.params.ParameterizedTest;
@@ -49,9 +52,21 @@
4952
import org.springframework.context.annotation.Configuration;
5053
import org.springframework.context.annotation.Import;
5154
import org.springframework.core.io.ClassPathResource;
55+
import org.springframework.dao.DuplicateKeyException;
5256
import org.springframework.dao.IncorrectResultSizeDataAccessException;
5357
import org.springframework.data.annotation.Id;
54-
import org.springframework.data.domain.*;
58+
import org.springframework.data.annotation.Transient;
59+
import org.springframework.data.domain.Example;
60+
import org.springframework.data.domain.ExampleMatcher;
61+
import org.springframework.data.domain.Limit;
62+
import org.springframework.data.domain.Page;
63+
import org.springframework.data.domain.PageRequest;
64+
import org.springframework.data.domain.Pageable;
65+
import org.springframework.data.domain.Persistable;
66+
import org.springframework.data.domain.ScrollPosition;
67+
import org.springframework.data.domain.Slice;
68+
import org.springframework.data.domain.Sort;
69+
import org.springframework.data.domain.Window;
5570
import org.springframework.data.jdbc.core.mapping.AggregateReference;
5671
import org.springframework.data.jdbc.repository.query.Modifying;
5772
import org.springframework.data.jdbc.repository.query.Query;
@@ -64,8 +79,8 @@
6479
import org.springframework.data.jdbc.testing.TestDatabaseFeatures;
6580
import org.springframework.data.relational.core.mapping.Column;
6681
import org.springframework.data.relational.core.mapping.MappedCollection;
67-
import org.springframework.data.relational.core.mapping.Table;
6882
import org.springframework.data.relational.core.mapping.Sequence;
83+
import org.springframework.data.relational.core.mapping.Table;
6984
import org.springframework.data.relational.core.mapping.event.AbstractRelationalEvent;
7085
import org.springframework.data.relational.core.mapping.event.AfterConvertEvent;
7186
import org.springframework.data.relational.core.sql.LockMode;
@@ -104,6 +119,8 @@ public class JdbcRepositoryIntegrationTests {
104119

105120
@Autowired NamedParameterJdbcTemplate template;
106121
@Autowired DummyEntityRepository repository;
122+
123+
@Autowired ProvidedIdEntityRepository providedIdEntityRepository;
107124
@Autowired MyEventListener eventListener;
108125
@Autowired RootRepository rootRepository;
109126
@Autowired WithDelimitedColumnRepository withDelimitedColumnRepository;
@@ -208,6 +225,18 @@ public void findAllFindsAllSpecifiedEntities() {
208225
.containsExactlyInAnyOrder(entity.getIdProp(), other.getIdProp());
209226
}
210227

228+
@Test // DATAJDBC-611
229+
public void testDuplicateKeyExceptionIsThrownInCaseOfUniqueKeyViolation() {
230+
231+
// given.
232+
ProvidedIdEntity first = ProvidedIdEntity.newInstance(1L, "name");
233+
ProvidedIdEntity second = ProvidedIdEntity.newInstance(1L, "other");
234+
235+
// when/then
236+
Assertions.assertThatCode(() -> providedIdEntityRepository.save(first)).doesNotThrowAnyException();
237+
Assertions.assertThatThrownBy(() -> providedIdEntityRepository.save(second)).isInstanceOf(DuplicateKeyException.class);
238+
}
239+
211240
@Test // DATAJDBC-97
212241
public void countsEntities() {
213242

@@ -1436,6 +1465,10 @@ interface DummyProjectExample {
14361465
String getName();
14371466
}
14381467

1468+
interface ProvidedIdEntityRepository extends CrudRepository<ProvidedIdEntity, Long> {
1469+
1470+
}
1471+
14391472
interface DummyEntityRepository extends CrudRepository<DummyEntity, Long>, QueryByExampleExecutor<DummyEntity> {
14401473

14411474
@Lock(LockMode.PESSIMISTIC_WRITE)
@@ -1543,6 +1576,11 @@ DummyEntityRepository dummyEntityRepository() {
15431576
return factory.getRepository(DummyEntityRepository.class);
15441577
}
15451578

1579+
@Bean
1580+
ProvidedIdEntityRepository providedIdEntityRepository() {
1581+
return factory.getRepository(ProvidedIdEntityRepository.class);
1582+
}
1583+
15461584
@Bean
15471585
RootRepository rootRepository() {
15481586
return factory.getRepository(RootRepository.class);
@@ -1886,6 +1924,37 @@ public String getName() {
18861924
}
18871925
}
18881926

1927+
static class ProvidedIdEntity implements Persistable<Long> {
1928+
1929+
@Id
1930+
private final Long id;
1931+
1932+
private String name;
1933+
1934+
@Transient
1935+
private boolean isNew;
1936+
1937+
private ProvidedIdEntity(Long id, String name, boolean isNew) {
1938+
this.id = id;
1939+
this.name = name;
1940+
this.isNew = isNew;
1941+
}
1942+
1943+
private static ProvidedIdEntity newInstance(Long id, String name) {
1944+
return new ProvidedIdEntity(id, name, true);
1945+
}
1946+
1947+
@Override
1948+
public Long getId() {
1949+
return id;
1950+
}
1951+
1952+
@Override
1953+
public boolean isNew() {
1954+
return isNew;
1955+
}
1956+
}
1957+
18891958
static class DummyEntity {
18901959

18911960
String name;

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

+6-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ DROP TABLE LEAF;
55
DROP TABLE WITH_DELIMITED_COLUMN;
66
DROP TABLE ENTITY_WITH_SEQUENCE;
77
DROP SEQUENCE ENTITY_SEQUENCE;
8+
DROP TABLE PROVIDED_ID_ENTITY;
89

910
CREATE TABLE dummy_entity
1011
(
@@ -55,4 +56,8 @@ CREATE TABLE ENTITY_WITH_SEQUENCE
5556
NAME VARCHAR(100)
5657
);
5758

58-
CREATE SEQUENCE ENTITY_SEQUENCE START WITH 1 INCREMENT BY 1 NO MAXVALUE;
59+
CREATE TABLE PROVIDED_ID_ENTITY
60+
(
61+
ID BIGINT PRIMARY KEY,
62+
NAME VARCHAR(30)
63+
);

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

+7-1
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,10 @@ 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;
51+
52+
CREATE TABLE PROVIDED_ID_ENTITY
53+
(
54+
ID BIGINT PRIMARY KEY,
55+
NAME VARCHAR(30)
56+
);

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

+7-1
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,10 @@ 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;
51+
52+
CREATE TABLE PROVIDED_ID_ENTITY
53+
(
54+
ID BIGINT PRIMARY KEY,
55+
NAME VARCHAR(30)
56+
);

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

+7-1
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,10 @@ 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;
51+
52+
CREATE TABLE PROVIDED_ID_ENTITY
53+
(
54+
ID BIGINT PRIMARY KEY,
55+
NAME VARCHAR(30)
56+
);

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

+8-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ DROP TABLE IF EXISTS LEAF;
55
DROP TABLE IF EXISTS WITH_DELIMITED_COLUMN;
66
DROP TABLE IF EXISTS ENTITY_WITH_SEQUENCE;
77
DROP SEQUENCE IF EXISTS ENTITY_SEQUENCE;
8+
DROP TABLE IF EXISTS PROVIDED_ID_ENTITY;
89

910
CREATE TABLE dummy_entity
1011
(
@@ -55,4 +56,10 @@ CREATE TABLE ENTITY_WITH_SEQUENCE
5556
NAME VARCHAR(100)
5657
);
5758

58-
CREATE SEQUENCE ENTITY_SEQUENCE START WITH 1 INCREMENT BY 1 NO MAXVALUE;
59+
CREATE SEQUENCE ENTITY_SEQUENCE START WITH 1 INCREMENT BY 1 NO MAXVALUE;
60+
61+
CREATE TABLE PROVIDED_ID_ENTITY
62+
(
63+
ID BIGINT PRIMARY KEY,
64+
NAME VARCHAR(30)
65+
);

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

+7-1
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,10 @@ CREATE TABLE WITH_DELIMITED_COLUMN
4242
ID BIGINT AUTO_INCREMENT PRIMARY KEY,
4343
`ORG.XTUNIT.IDENTIFIER` VARCHAR(100),
4444
STYPE VARCHAR(100)
45-
);
45+
);
46+
47+
CREATE TABLE PROVIDED_ID_ENTITY
48+
(
49+
ID BIGINT PRIMARY KEY,
50+
NAME VARCHAR(30)
51+
);

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

+8-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ DROP TABLE LEAF CASCADE CONSTRAINTS PURGE;
55
DROP TABLE WITH_DELIMITED_COLUMN CASCADE CONSTRAINTS PURGE;
66
DROP TABLE ENTITY_WITH_SEQUENCE CASCADE CONSTRAINTS PURGE;
77
DROP SEQUENCE ENTITY_SEQUENCE;
8+
DROP TABLE PROVIDED_ID_ENTITY CASCADE CONSTRAINTS PURGE;
89

910
CREATE TABLE DUMMY_ENTITY
1011
(
@@ -55,4 +56,10 @@ CREATE TABLE ENTITY_WITH_SEQUENCE
5556
NAME VARCHAR(100)
5657
);
5758

58-
CREATE SEQUENCE ENTITY_SEQUENCE START WITH 1 INCREMENT BY 1;
59+
CREATE SEQUENCE ENTITY_SEQUENCE START WITH 1 INCREMENT BY 1;
60+
61+
CREATE TABLE PROVIDED_ID_ENTITY
62+
(
63+
ID BIGINT PRIMARY KEY,
64+
NAME VARCHAR(30)
65+
);

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

+8-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ DROP TABLE LEAF;
55
DROP TABLE WITH_DELIMITED_COLUMN;
66
DROP TABLE ENTITY_WITH_SEQUENCE;
77
DROP SEQUENCE ENTITY_SEQUENCE;
8+
DROP TABLE PROVIDED_ID_ENTITY;
89

910
CREATE TABLE dummy_entity
1011
(
@@ -55,4 +56,10 @@ CREATE TABLE ENTITY_WITH_SEQUENCE
5556
NAME VARCHAR(100)
5657
);
5758

58-
CREATE SEQUENCE "ENTITY_SEQUENCE" START WITH 1 INCREMENT BY 1 NO MAXVALUE;
59+
CREATE SEQUENCE "ENTITY_SEQUENCE" START WITH 1 INCREMENT BY 1 NO MAXVALUE;
60+
61+
CREATE TABLE PROVIDED_ID_ENTITY
62+
(
63+
ID BIGINT PRIMARY KEY,
64+
NAME VARCHAR(30)
65+
);

0 commit comments

Comments
 (0)