Skip to content

Commit 30d446e

Browse files
authored
Associate entities only once per unique combination (#891)
1 parent 6ff23d1 commit 30d446e

File tree

25 files changed

+315
-5
lines changed

25 files changed

+315
-5
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package org.seasar.doma.internal.util;
2+
3+
import java.util.HashSet;
4+
import java.util.Set;
5+
6+
public class Combinations<T> {
7+
8+
private final Set<Pair<T, T>> pairs = new HashSet<>();
9+
10+
public boolean contains(Pair<T, T> pair) {
11+
if (pairs.contains(pair)) {
12+
return true;
13+
}
14+
return pairs.contains(new Pair<>(pair.snd, pair.fst));
15+
}
16+
17+
public void add(Pair<T, T> pair) {
18+
pairs.add(pair);
19+
}
20+
}

doma-core/src/main/java/org/seasar/doma/jdbc/criteria/command/AssociateCommand.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.util.Map;
88
import java.util.Objects;
99
import java.util.function.BiFunction;
10+
import org.seasar.doma.internal.util.Combinations;
1011
import org.seasar.doma.internal.util.Pair;
1112
import org.seasar.doma.jdbc.command.Command;
1213
import org.seasar.doma.jdbc.command.SelectCommand;
@@ -32,6 +33,7 @@ public AssociateCommand(
3233
@SuppressWarnings("unchecked")
3334
public List<ENTITY> execute() {
3435
Map<EntityKey, Object> cache = new LinkedHashMap<>();
36+
Combinations<EntityKey> combinations = new Combinations<>();
3537
SelectCommand<List<EntityPool>> command =
3638
new SelectCommand<>(
3739
query, new EntityPoolIterationHandler(context.getProjectionEntityMetamodels()));
@@ -55,7 +57,7 @@ public List<ENTITY> execute() {
5557
});
5658
associationCandidate.put(key.getEntityMetamodel(), new Pair<>(key, entity));
5759
}
58-
associate(cache, associationCandidate);
60+
associate(cache, combinations, associationCandidate);
5961
}
6062
return (List<ENTITY>)
6163
cache.entrySet().stream()
@@ -66,6 +68,7 @@ public List<ENTITY> execute() {
6668

6769
private void associate(
6870
Map<EntityKey, Object> cache,
71+
Combinations<EntityKey> combinations,
6972
Map<EntityMetamodel<?>, Pair<EntityKey, Object>> associationCandidate) {
7073
for (Map.Entry<Pair<EntityMetamodel<?>, EntityMetamodel<?>>, BiFunction<Object, Object, Object>>
7174
e : context.associations.entrySet()) {
@@ -76,11 +79,16 @@ private void associate(
7679
if (keyAndEntity1 == null || keyAndEntity2 == null) {
7780
continue;
7881
}
82+
Pair<EntityKey, EntityKey> keyPair = new Pair<>(keyAndEntity1.fst, keyAndEntity2.fst);
83+
if (combinations.contains(keyPair)) {
84+
continue;
85+
}
7986
Object newEntity = associator.apply(keyAndEntity1.snd, keyAndEntity2.snd);
8087
if (newEntity != null) {
8188
cache.replace(keyAndEntity1.fst, newEntity);
8289
associationCandidate.replace(metamodelPair.fst, new Pair<>(keyAndEntity1.fst, newEntity));
8390
}
91+
combinations.add(keyPair);
8492
}
8593
}
8694

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package org.seasar.doma.internal.util;
2+
3+
import static org.junit.jupiter.api.Assertions.assertFalse;
4+
import static org.junit.jupiter.api.Assertions.assertTrue;
5+
6+
import org.junit.jupiter.api.Test;
7+
8+
class CombinationsTest {
9+
10+
@Test
11+
void test() {
12+
Combinations<String> combinations = new Combinations<>();
13+
combinations.add(new Pair<>("A", "B"));
14+
combinations.add(new Pair<>("A", "C"));
15+
16+
assertTrue(combinations.contains(new Pair<>("A", "B")));
17+
assertTrue(combinations.contains(new Pair<>("B", "A")));
18+
assertTrue(combinations.contains(new Pair<>("A", "C")));
19+
assertTrue(combinations.contains(new Pair<>("C", "A")));
20+
assertFalse(combinations.contains(new Pair<>("B", "C")));
21+
assertFalse(combinations.contains(new Pair<>("C", "B")));
22+
}
23+
}

integration-test-common/src/main/resources/META-INF/org/seasar/doma/it/dao/ScriptDao/create-db2.script

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ CREATE TABLE SEQUENCE_STRATEGY2(ID INTEGER NOT NULL PRIMARY KEY, VALUE VARCHAR(1
2828
CREATE TABLE TABLE_STRATEGY(ID INTEGER NOT NULL PRIMARY KEY, VALUE VARCHAR(10));
2929
CREATE TABLE TABLE_STRATEGY2(ID INTEGER NOT NULL PRIMARY KEY, VALUE VARCHAR(10));
3030

31+
CREATE TABLE TEAM(ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR(20));
32+
CREATE TABLE PLAYER(ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR(20), TEAM_ID INTEGER);
33+
CREATE TABLE COACH(ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR(20), TEAM_ID INTEGER);
34+
3135
INSERT INTO DEPARTMENT VALUES(1,10,'ACCOUNTING','NEW YORK',1);
3236
INSERT INTO DEPARTMENT VALUES(2,20,'RESEARCH','DALLAS',1);
3337
INSERT INTO DEPARTMENT VALUES(3,30,'SALES','CHICAGO',1);

integration-test-common/src/main/resources/META-INF/org/seasar/doma/it/dao/ScriptDao/create-h2.script

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ CREATE TABLE SEQUENCE_STRATEGY2(ID INTEGER NOT NULL PRIMARY KEY, VALUE VARCHAR(1
2929
CREATE TABLE TABLE_STRATEGY(ID INTEGER NOT NULL PRIMARY KEY, VALUE VARCHAR(10));
3030
CREATE TABLE TABLE_STRATEGY2(ID INTEGER NOT NULL PRIMARY KEY, VALUE VARCHAR(10));
3131

32+
CREATE TABLE TEAM(ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR(20));
33+
CREATE TABLE PLAYER(ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR(20), TEAM_ID INTEGER);
34+
CREATE TABLE COACH(ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR(20), TEAM_ID INTEGER);
35+
3236
INSERT INTO DEPARTMENT VALUES(1,10,'ACCOUNTING','NEW YORK',1);
3337
INSERT INTO DEPARTMENT VALUES(2,20,'RESEARCH','DALLAS',1);
3438
INSERT INTO DEPARTMENT VALUES(3,30,'SALES','CHICAGO',1);

integration-test-common/src/main/resources/META-INF/org/seasar/doma/it/dao/ScriptDao/create-hsqldb.script

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ CREATE TABLE SEQUENCE_STRATEGY2(ID INTEGER NOT NULL PRIMARY KEY, VALUE VARCHAR(1
3333
CREATE TABLE TABLE_STRATEGY(ID INTEGER NOT NULL PRIMARY KEY, VALUE VARCHAR(10));
3434
CREATE TABLE TABLE_STRATEGY2(ID INTEGER NOT NULL PRIMARY KEY, VALUE VARCHAR(10));
3535

36+
CREATE TABLE TEAM(ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR(20));
37+
CREATE TABLE PLAYER(ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR(20), TEAM_ID INTEGER);
38+
CREATE TABLE COACH(ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR(20), TEAM_ID INTEGER);
39+
3640
INSERT INTO DEPARTMENT VALUES(1,10,'ACCOUNTING','NEW YORK',1);
3741
INSERT INTO DEPARTMENT VALUES(2,20,'RESEARCH','DALLAS',1);
3842
INSERT INTO DEPARTMENT VALUES(3,30,'SALES','CHICAGO',1);

integration-test-common/src/main/resources/META-INF/org/seasar/doma/it/dao/ScriptDao/create-mssql.script

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ CREATE TABLE TABLE_STRATEGY(ID INT NOT NULL PRIMARY KEY, VALUE VARCHAR(10));
2626
CREATE TABLE TABLE_STRATEGY2(ID INT NOT NULL PRIMARY KEY, VALUE VARCHAR(10));
2727
CREATE TABLE TABLE_STRATEGY5(ID INT NOT NULL PRIMARY KEY, VALUE VARCHAR(10));
2828

29+
CREATE TABLE TEAM(ID INT NOT NULL PRIMARY KEY, NAME VARCHAR(20));
30+
CREATE TABLE PLAYER(ID INT NOT NULL PRIMARY KEY, NAME VARCHAR(20), TEAM_ID INT);
31+
CREATE TABLE COACH(ID INT NOT NULL PRIMARY KEY, NAME VARCHAR(20), TEAM_ID INT);
32+
2933
INSERT INTO DEPARTMENT VALUES(1,10,'ACCOUNTING','NEW YORK',1);
3034
INSERT INTO DEPARTMENT VALUES(2,20,'RESEARCH','DALLAS',1);
3135
INSERT INTO DEPARTMENT VALUES(3,30,'SALES','CHICAGO',1);

integration-test-common/src/main/resources/META-INF/org/seasar/doma/it/dao/ScriptDao/create-mssql2008.script

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ CREATE TABLE TABLE_STRATEGY(ID INT NOT NULL PRIMARY KEY, VALUE VARCHAR(10));
2626
CREATE TABLE TABLE_STRATEGY2(ID INT NOT NULL PRIMARY KEY, VALUE VARCHAR(10));
2727
CREATE TABLE TABLE_STRATEGY5(ID INT NOT NULL PRIMARY KEY, VALUE VARCHAR(10));
2828

29+
CREATE TABLE TEAM(ID INT NOT NULL PRIMARY KEY, NAME VARCHAR(20));
30+
CREATE TABLE PLAYER(ID INT NOT NULL PRIMARY KEY, NAME VARCHAR(20), TEAM_ID INT);
31+
CREATE TABLE COACH(ID INT NOT NULL PRIMARY KEY, NAME VARCHAR(20), TEAM_ID INT);
32+
2933
INSERT INTO DEPARTMENT VALUES(1,10,'ACCOUNTING','NEW YORK',1);
3034
INSERT INTO DEPARTMENT VALUES(2,20,'RESEARCH','DALLAS',1);
3135
INSERT INTO DEPARTMENT VALUES(3,30,'SALES','CHICAGO',1);

integration-test-common/src/main/resources/META-INF/org/seasar/doma/it/dao/ScriptDao/create-mysql.script

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ CREATE TABLE SEQUENCE_STRATEGY2(ID INTEGER NOT NULL PRIMARY KEY, VALUE VARCHAR(1
2525
CREATE TABLE TABLE_STRATEGY(ID INTEGER NOT NULL PRIMARY KEY, VALUE VARCHAR(10));
2626
CREATE TABLE TABLE_STRATEGY2(ID INTEGER NOT NULL PRIMARY KEY, VALUE VARCHAR(10));
2727

28+
CREATE TABLE TEAM(ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR(20));
29+
CREATE TABLE PLAYER(ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR(20), TEAM_ID INTEGER);
30+
CREATE TABLE COACH(ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR(20), TEAM_ID INTEGER);
31+
2832
INSERT INTO DEPARTMENT VALUES(1,10,'ACCOUNTING','NEW YORK',1);
2933
INSERT INTO DEPARTMENT VALUES(2,20,'RESEARCH','DALLAS',1);
3034
INSERT INTO DEPARTMENT VALUES(3,30,'SALES','CHICAGO',1);

integration-test-common/src/main/resources/META-INF/org/seasar/doma/it/dao/ScriptDao/create-oracle.script

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ CREATE TABLE SEQUENCE_STRATEGY2(ID NUMERIC(8) NOT NULL PRIMARY KEY, VALUE VARCHA
2929
CREATE TABLE TABLE_STRATEGY(ID NUMERIC(8) NOT NULL PRIMARY KEY, VALUE VARCHAR2(10));
3030
CREATE TABLE TABLE_STRATEGY2(ID NUMERIC(8) NOT NULL PRIMARY KEY, VALUE VARCHAR2(10));
3131

32+
CREATE TABLE TEAM(ID NUMERIC(8) NOT NULL PRIMARY KEY, NAME VARCHAR(20));
33+
CREATE TABLE PLAYER(ID NUMERIC(8) NOT NULL PRIMARY KEY, NAME VARCHAR(20), TEAM_ID NUMERIC(8));
34+
CREATE TABLE COACH(ID NUMERIC(8) NOT NULL PRIMARY KEY, NAME VARCHAR(20), TEAM_ID NUMERIC(8));
35+
3236
CREATE INDEX IX_EMPLOYEE_1 ON EMPLOYEE (EMPLOYEE_NAME);
3337

3438
INSERT INTO DEPARTMENT VALUES(1,10,'ACCOUNTING','NEW YORK',1);

0 commit comments

Comments
 (0)