Skip to content

Commit 174defd

Browse files
committed
Fix DELETE queries with custom ID column names
- Remove getIdDefiningParentPath() usage in JdbcDeleteQueryCreator - Add integration test for @column annotation on @id fields in DELETE operations Signed-off-by: Huiyeongkim <[email protected]>
1 parent ca45cd5 commit 174defd

File tree

3 files changed

+136
-2
lines changed

3 files changed

+136
-2
lines changed

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/JdbcDeleteQueryCreator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,11 @@ private void deleteRelations(RelationalPersistentEntity<?> entity, Select parent
150150

151151
Condition inCondition = Conditions.in(expression, parentSelect);
152152

153-
List<Column> parentIdColumns = aggregatePath.getIdDefiningParentPath().getTableInfo().idColumnInfos()
153+
List<Column> idColumns = aggregatePath.getTableInfo().idColumnInfos()
154154
.toColumnList(table);
155155

156156
Select select = StatementBuilder.select( //
157-
parentIdColumns //
157+
idColumns //
158158
).from(table) //
159159
.where(inCondition) //
160160
.build();
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package org.springframework.data.jdbc.repository;
2+
3+
import static org.assertj.core.api.Assertions.*;
4+
5+
import java.util.HashMap;
6+
import java.util.HashSet;
7+
import java.util.Set;
8+
9+
import org.junit.jupiter.api.Test;
10+
import org.springframework.beans.factory.annotation.Autowired;
11+
import org.springframework.context.annotation.Bean;
12+
import org.springframework.context.annotation.Configuration;
13+
import org.springframework.context.annotation.Import;
14+
import org.springframework.data.annotation.Id;
15+
import org.springframework.data.relational.core.mapping.Column;
16+
import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactory;
17+
import org.springframework.data.jdbc.testing.DatabaseType;
18+
import org.springframework.data.jdbc.testing.EnabledOnDatabase;
19+
import org.springframework.data.jdbc.testing.IntegrationTest;
20+
import org.springframework.data.jdbc.testing.TestConfiguration;
21+
import org.springframework.data.repository.CrudRepository;
22+
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
23+
24+
/**
25+
* Integration tests for custom ID column names with @Column annotation in DELETE operations.
26+
* This tests the fix for DATAJDBC-2123.
27+
*/
28+
@IntegrationTest
29+
@EnabledOnDatabase(DatabaseType.HSQL)
30+
class JdbcRepositoryWithCollectionsCustomIdIntegrationTests {
31+
32+
@Autowired NamedParameterJdbcTemplate template;
33+
@Autowired CustomIdEntityRepository repository;
34+
35+
private static CustomIdEntity createCustomIdEntity() {
36+
CustomIdEntity entity = new CustomIdEntity();
37+
entity.name = "Custom ID Entity Name";
38+
return entity;
39+
}
40+
41+
@Test // DATAJDBC-2123
42+
void deleteByNameWithCustomIdColumn() {
43+
44+
CustomIdChildElement element1 = createCustomIdChildElement("one");
45+
CustomIdChildElement element2 = createCustomIdChildElement("two");
46+
47+
CustomIdEntity entity = createCustomIdEntity();
48+
entity.content.add(element1);
49+
entity.content.add(element2);
50+
51+
entity = repository.save(entity);
52+
53+
assertThat(repository.deleteByName("Custom ID Entity Name")).isEqualTo(1);
54+
55+
assertThat(repository.findById(entity.id)).isEmpty();
56+
57+
Long count = template.queryForObject("select count(1) from custom_id_grand_child_element", new HashMap<>(), Long.class);
58+
assertThat(count).isEqualTo(0);
59+
}
60+
61+
private CustomIdChildElement createCustomIdChildElement(String name) {
62+
63+
CustomIdChildElement element = new CustomIdChildElement();
64+
element.name = name;
65+
element.content.add(createCustomIdGrandChildElement(name + "1"));
66+
element.content.add(createCustomIdGrandChildElement(name + "2"));
67+
return element;
68+
}
69+
70+
private CustomIdGrandChildElement createCustomIdGrandChildElement(String content) {
71+
72+
CustomIdGrandChildElement element = new CustomIdGrandChildElement();
73+
element.content = content;
74+
return element;
75+
}
76+
77+
interface CustomIdEntityRepository extends CrudRepository<CustomIdEntity, Long> {
78+
long deleteByName(String name);
79+
}
80+
81+
@Configuration
82+
@Import(TestConfiguration.class)
83+
static class Config {
84+
85+
@Autowired JdbcRepositoryFactory factory;
86+
87+
@Bean
88+
Class<?> testClass() {
89+
return JdbcRepositoryWithCollectionsCustomIdIntegrationTests.class;
90+
}
91+
92+
@Bean
93+
CustomIdEntityRepository customIdEntityRepository() {
94+
return factory.getRepository(CustomIdEntityRepository.class);
95+
}
96+
}
97+
98+
static class CustomIdEntity {
99+
100+
String name;
101+
Set<CustomIdChildElement> content = new HashSet<>();
102+
@Id private Long id;
103+
}
104+
105+
static class CustomIdChildElement {
106+
107+
String name;
108+
Set<CustomIdGrandChildElement> content = new HashSet<>();
109+
@Id @Column("CHILD_ID") private Long id;
110+
}
111+
112+
static class CustomIdGrandChildElement {
113+
114+
String content;
115+
@Id private Long id;
116+
}
117+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
CREATE TABLE CUSTOM_ID_ENTITY
2+
(
3+
ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY,
4+
NAME VARCHAR(100)
5+
);
6+
CREATE TABLE CUSTOM_ID_CHILD_ELEMENT
7+
(
8+
CHILD_ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY,
9+
NAME VARCHAR(100),
10+
CUSTOM_ID_ENTITY BIGINT
11+
);
12+
CREATE TABLE CUSTOM_ID_GRAND_CHILD_ELEMENT
13+
(
14+
ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY,
15+
CONTENT VARCHAR(100),
16+
CUSTOM_ID_CHILD_ELEMENT BIGINT
17+
);

0 commit comments

Comments
 (0)