Skip to content

Commit 93b6ecd

Browse files
authored
Merge pull request #406 from domaframework/batch
Support batch statements in Criteria API
2 parents 2e51ff8 + 5b963a1 commit 93b6ecd

23 files changed

+970
-223
lines changed

docs/criteria-api.rst

Lines changed: 222 additions & 91 deletions
Large diffs are not rendered by default.

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

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
package org.seasar.doma.jdbc.criteria;
22

3+
import java.util.List;
34
import java.util.Objects;
45
import java.util.function.Consumer;
56
import org.seasar.doma.jdbc.Config;
67
import org.seasar.doma.jdbc.criteria.context.Options;
78
import org.seasar.doma.jdbc.criteria.context.SelectContext;
89
import org.seasar.doma.jdbc.criteria.declaration.SelectFromDeclaration;
910
import org.seasar.doma.jdbc.criteria.def.EntityDef;
11+
import org.seasar.doma.jdbc.criteria.statement.EntityqlBatchDeleteStatement;
12+
import org.seasar.doma.jdbc.criteria.statement.EntityqlBatchInsertStatement;
13+
import org.seasar.doma.jdbc.criteria.statement.EntityqlBatchUpdateStatement;
1014
import org.seasar.doma.jdbc.criteria.statement.EntityqlDeleteStatement;
1115
import org.seasar.doma.jdbc.criteria.statement.EntityqlInsertStatement;
1216
import org.seasar.doma.jdbc.criteria.statement.EntityqlSelectStatement;
1317
import org.seasar.doma.jdbc.criteria.statement.EntityqlUpdateStatement;
18+
import org.seasar.doma.jdbc.criteria.statement.Statement;
1419

1520
public class Entityql {
1621

@@ -35,14 +40,13 @@ public <ENTITY> EntityqlSelectStatement<ENTITY> from(
3540
return new EntityqlSelectStatement<>(config, declaration);
3641
}
3742

38-
public <ENTITY> EntityqlUpdateStatement<ENTITY> update(
39-
EntityDef<ENTITY> entityDef, ENTITY entity) {
43+
public <ENTITY> Statement<ENTITY> update(EntityDef<ENTITY> entityDef, ENTITY entity) {
4044
Objects.requireNonNull(entityDef);
4145
Objects.requireNonNull(entity);
4246
return update(entityDef, entity, options -> {});
4347
}
4448

45-
public <ENTITY> EntityqlUpdateStatement<ENTITY> update(
49+
public <ENTITY> Statement<ENTITY> update(
4650
EntityDef<ENTITY> entityDef, ENTITY entity, Consumer<Options> optionsConsumer) {
4751
Objects.requireNonNull(entityDef);
4852
Objects.requireNonNull(entity);
@@ -52,14 +56,13 @@ public <ENTITY> EntityqlUpdateStatement<ENTITY> update(
5256
return new EntityqlUpdateStatement<>(config, entityDef, entity, options);
5357
}
5458

55-
public <ENTITY> EntityqlDeleteStatement<ENTITY> delete(
56-
EntityDef<ENTITY> entityDef, ENTITY entity) {
59+
public <ENTITY> Statement<ENTITY> delete(EntityDef<ENTITY> entityDef, ENTITY entity) {
5760
Objects.requireNonNull(entityDef);
5861
Objects.requireNonNull(entity);
5962
return delete(entityDef, entity, options -> {});
6063
}
6164

62-
public <ENTITY> EntityqlDeleteStatement<ENTITY> delete(
65+
public <ENTITY> Statement<ENTITY> delete(
6366
EntityDef<ENTITY> entityDef, ENTITY entity, Consumer<Options> optionsConsumer) {
6467
Objects.requireNonNull(entityDef);
6568
Objects.requireNonNull(entity);
@@ -69,14 +72,13 @@ public <ENTITY> EntityqlDeleteStatement<ENTITY> delete(
6972
return new EntityqlDeleteStatement<>(config, entityDef, entity, options);
7073
}
7174

72-
public <ENTITY> EntityqlInsertStatement<ENTITY> insert(
73-
EntityDef<ENTITY> entityDef, ENTITY entity) {
75+
public <ENTITY> Statement<ENTITY> insert(EntityDef<ENTITY> entityDef, ENTITY entity) {
7476
Objects.requireNonNull(entityDef);
7577
Objects.requireNonNull(entity);
7678
return insert(entityDef, entity, options -> {});
7779
}
7880

79-
public <ENTITY> EntityqlInsertStatement<ENTITY> insert(
81+
public <ENTITY> Statement<ENTITY> insert(
8082
EntityDef<ENTITY> entityDef, ENTITY entity, Consumer<Options> optionsConsumer) {
8183
Objects.requireNonNull(entityDef);
8284
Objects.requireNonNull(entity);
@@ -85,4 +87,55 @@ public <ENTITY> EntityqlInsertStatement<ENTITY> insert(
8587
optionsConsumer.accept(options);
8688
return new EntityqlInsertStatement<>(config, entityDef, entity, options);
8789
}
90+
91+
public <ENTITY> Statement<List<ENTITY>> update(
92+
EntityDef<ENTITY> entityDef, List<ENTITY> entities) {
93+
Objects.requireNonNull(entityDef);
94+
Objects.requireNonNull(entities);
95+
return update(entityDef, entities, options -> {});
96+
}
97+
98+
public <ENTITY> Statement<List<ENTITY>> update(
99+
EntityDef<ENTITY> entityDef, List<ENTITY> entities, Consumer<Options> optionsConsumer) {
100+
Objects.requireNonNull(entityDef);
101+
Objects.requireNonNull(entities);
102+
Objects.requireNonNull(optionsConsumer);
103+
Options options = new Options();
104+
optionsConsumer.accept(options);
105+
return new EntityqlBatchUpdateStatement<>(config, entityDef, entities, options);
106+
}
107+
108+
public <ENTITY> Statement<List<ENTITY>> delete(
109+
EntityDef<ENTITY> entityDef, List<ENTITY> entities) {
110+
Objects.requireNonNull(entityDef);
111+
Objects.requireNonNull(entities);
112+
return delete(entityDef, entities, options -> {});
113+
}
114+
115+
public <ENTITY> Statement<List<ENTITY>> delete(
116+
EntityDef<ENTITY> entityDef, List<ENTITY> entities, Consumer<Options> optionsConsumer) {
117+
Objects.requireNonNull(entityDef);
118+
Objects.requireNonNull(entities);
119+
Objects.requireNonNull(optionsConsumer);
120+
Options options = new Options();
121+
optionsConsumer.accept(options);
122+
return new EntityqlBatchDeleteStatement<>(config, entityDef, entities, options);
123+
}
124+
125+
public <ENTITY> Statement<List<ENTITY>> insert(
126+
EntityDef<ENTITY> entityDef, List<ENTITY> entities) {
127+
Objects.requireNonNull(entityDef);
128+
Objects.requireNonNull(entities);
129+
return insert(entityDef, entities, options -> {});
130+
}
131+
132+
public <ENTITY> Statement<List<ENTITY>> insert(
133+
EntityDef<ENTITY> entityDef, List<ENTITY> entities, Consumer<Options> optionsConsumer) {
134+
Objects.requireNonNull(entityDef);
135+
Objects.requireNonNull(entities);
136+
Objects.requireNonNull(optionsConsumer);
137+
Options options = new Options();
138+
optionsConsumer.accept(options);
139+
return new EntityqlBatchInsertStatement<>(config, entityDef, entities, options);
140+
}
88141
}

doma-core/src/main/java/org/seasar/doma/jdbc/criteria/statement/AbstractStatement.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
11
package org.seasar.doma.jdbc.criteria.statement;
22

3+
import java.lang.reflect.Method;
34
import java.util.Objects;
45
import java.util.function.Function;
6+
import org.seasar.doma.DomaException;
57
import org.seasar.doma.jdbc.CommentContext;
68
import org.seasar.doma.jdbc.Config;
79
import org.seasar.doma.jdbc.Sql;
8-
import org.seasar.doma.jdbc.SqlLogType;
910
import org.seasar.doma.jdbc.command.Command;
11+
import org.seasar.doma.message.Message;
1012

1113
public abstract class AbstractStatement<RESULT> implements Statement<RESULT> {
1214

13-
private static final SqlLogType defaultSqlLogType = SqlLogType.FORMATTED;
14-
private static final String defaultComment = "";
1515
protected static final String EXECUTE_METHOD_NAME = "execute";
16+
protected static final Method EXECUTE_METHOD;
17+
18+
static {
19+
try {
20+
EXECUTE_METHOD = Statement.class.getMethod(EXECUTE_METHOD_NAME);
21+
} catch (NoSuchMethodException e) {
22+
throw new DomaException(Message.DOMA6005, e, EXECUTE_METHOD_NAME);
23+
}
24+
}
1625

1726
protected final Config config;
1827

@@ -35,7 +44,8 @@ public Sql<?> asSql() {
3544
protected Function<String, String> createCommenter(String comment) {
3645
return sql -> {
3746
CommentContext context =
38-
new CommentContext(getClass().getName(), EXECUTE_METHOD_NAME, config, null, comment);
47+
new CommentContext(
48+
getClass().getName(), EXECUTE_METHOD_NAME, config, EXECUTE_METHOD, comment);
3949
return config.getCommenter().comment(sql, context);
4050
};
4151
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package org.seasar.doma.jdbc.criteria.statement;
2+
3+
import java.util.Collections;
4+
import java.util.List;
5+
import java.util.Objects;
6+
import org.seasar.doma.jdbc.InParameter;
7+
import org.seasar.doma.jdbc.Sql;
8+
import org.seasar.doma.jdbc.SqlKind;
9+
import org.seasar.doma.jdbc.SqlLogType;
10+
11+
public class EmptySql implements Sql<InParameter<?>> {
12+
13+
private static final String MESSAGE = "This SQL is empty because target entities are empty.";
14+
private final SqlKind sqlKind;
15+
16+
public EmptySql(SqlKind sqlKind) {
17+
this.sqlKind = Objects.requireNonNull(sqlKind);
18+
}
19+
20+
@Override
21+
public SqlKind getKind() {
22+
return sqlKind;
23+
}
24+
25+
@Override
26+
public String getRawSql() {
27+
return MESSAGE;
28+
}
29+
30+
@Override
31+
public String getFormattedSql() {
32+
return MESSAGE;
33+
}
34+
35+
@Override
36+
public String getSqlFilePath() {
37+
return null;
38+
}
39+
40+
@Override
41+
public List<InParameter<?>> getParameters() {
42+
return Collections.emptyList();
43+
}
44+
45+
@Override
46+
public SqlLogType getSqlLogType() {
47+
return SqlLogType.FORMATTED;
48+
}
49+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package org.seasar.doma.jdbc.criteria.statement;
2+
3+
import java.util.List;
4+
import java.util.Objects;
5+
import org.seasar.doma.jdbc.Config;
6+
import org.seasar.doma.jdbc.Sql;
7+
import org.seasar.doma.jdbc.SqlKind;
8+
import org.seasar.doma.jdbc.command.BatchDeleteCommand;
9+
import org.seasar.doma.jdbc.command.Command;
10+
import org.seasar.doma.jdbc.criteria.context.Options;
11+
import org.seasar.doma.jdbc.criteria.def.EntityDef;
12+
import org.seasar.doma.jdbc.entity.EntityType;
13+
import org.seasar.doma.jdbc.query.AutoBatchDeleteQuery;
14+
import org.seasar.doma.jdbc.query.Query;
15+
16+
public class EntityqlBatchDeleteStatement<ENTITY> extends AbstractStatement<List<ENTITY>> {
17+
18+
private static final EmptySql EMPTY_SQL = new EmptySql(SqlKind.BATCH_DELETE);
19+
private final EntityDef<ENTITY> entityDef;
20+
private final List<ENTITY> entities;
21+
private final Options options;
22+
23+
public EntityqlBatchDeleteStatement(
24+
Config config, EntityDef<ENTITY> entityDef, List<ENTITY> entities, Options options) {
25+
super(Objects.requireNonNull(config));
26+
this.entityDef = Objects.requireNonNull(entityDef);
27+
this.entities = Objects.requireNonNull(entities);
28+
this.options = Objects.requireNonNull(options);
29+
}
30+
31+
@Override
32+
protected Command<List<ENTITY>> createCommand() {
33+
EntityType<ENTITY> entityType = entityDef.asType();
34+
AutoBatchDeleteQuery<ENTITY> query =
35+
config.getQueryImplementors().createAutoBatchDeleteQuery(EXECUTE_METHOD, entityType);
36+
query.setMethod(EXECUTE_METHOD);
37+
query.setConfig(config);
38+
query.setEntities(entities);
39+
query.setCallerClassName(getClass().getName());
40+
query.setCallerMethodName(EXECUTE_METHOD_NAME);
41+
query.setQueryTimeout(config.getQueryTimeout());
42+
query.setBatchSize(config.getBatchSize());
43+
query.setSqlLogType(options.sqlLogType());
44+
query.setVersionIgnored(false);
45+
query.setOptimisticLockExceptionSuppressed(false);
46+
query.setMessage(options.comment());
47+
query.prepare();
48+
BatchDeleteCommand command =
49+
config.getCommandImplementors().createBatchDeleteCommand(EXECUTE_METHOD, query);
50+
return new Command<List<ENTITY>>() {
51+
@Override
52+
public Query getQuery() {
53+
return query;
54+
}
55+
56+
@Override
57+
public List<ENTITY> execute() {
58+
command.execute();
59+
query.complete();
60+
return query.getEntities();
61+
}
62+
};
63+
}
64+
65+
@Override
66+
public Sql<?> asSql() {
67+
if (entities.isEmpty()) {
68+
return EMPTY_SQL;
69+
}
70+
return super.asSql();
71+
}
72+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package org.seasar.doma.jdbc.criteria.statement;
2+
3+
import java.util.List;
4+
import java.util.Objects;
5+
import org.seasar.doma.jdbc.Config;
6+
import org.seasar.doma.jdbc.Sql;
7+
import org.seasar.doma.jdbc.SqlKind;
8+
import org.seasar.doma.jdbc.command.BatchInsertCommand;
9+
import org.seasar.doma.jdbc.command.Command;
10+
import org.seasar.doma.jdbc.criteria.context.Options;
11+
import org.seasar.doma.jdbc.criteria.def.EntityDef;
12+
import org.seasar.doma.jdbc.entity.EntityType;
13+
import org.seasar.doma.jdbc.query.AutoBatchInsertQuery;
14+
import org.seasar.doma.jdbc.query.Query;
15+
16+
public class EntityqlBatchInsertStatement<ENTITY> extends AbstractStatement<List<ENTITY>> {
17+
18+
private static final EmptySql EMPTY_SQL = new EmptySql(SqlKind.BATCH_INSERT);
19+
private final EntityDef<ENTITY> entityDef;
20+
private final List<ENTITY> entities;
21+
private final Options options;
22+
23+
public EntityqlBatchInsertStatement(
24+
Config config, EntityDef<ENTITY> entityDef, List<ENTITY> entities, Options options) {
25+
super(Objects.requireNonNull(config));
26+
this.entityDef = Objects.requireNonNull(entityDef);
27+
this.entities = Objects.requireNonNull(entities);
28+
this.options = Objects.requireNonNull(options);
29+
}
30+
31+
@Override
32+
protected Command<List<ENTITY>> createCommand() {
33+
EntityType<ENTITY> entityType = entityDef.asType();
34+
AutoBatchInsertQuery<ENTITY> query =
35+
config.getQueryImplementors().createAutoBatchInsertQuery(EXECUTE_METHOD, entityType);
36+
query.setMethod(EXECUTE_METHOD);
37+
query.setConfig(config);
38+
query.setEntities(entities);
39+
query.setCallerClassName(getClass().getName());
40+
query.setCallerMethodName(EXECUTE_METHOD_NAME);
41+
query.setQueryTimeout(config.getQueryTimeout());
42+
query.setBatchSize(config.getBatchSize());
43+
query.setSqlLogType(options.sqlLogType());
44+
query.setIncludedPropertyNames();
45+
query.setExcludedPropertyNames();
46+
query.setMessage(options.comment());
47+
query.prepare();
48+
BatchInsertCommand command =
49+
config.getCommandImplementors().createBatchInsertCommand(EXECUTE_METHOD, query);
50+
return new Command<List<ENTITY>>() {
51+
@Override
52+
public Query getQuery() {
53+
return query;
54+
}
55+
56+
@Override
57+
public List<ENTITY> execute() {
58+
command.execute();
59+
query.complete();
60+
return query.getEntities();
61+
}
62+
};
63+
}
64+
65+
@Override
66+
public Sql<?> asSql() {
67+
if (entities.isEmpty()) {
68+
return EMPTY_SQL;
69+
}
70+
return super.asSql();
71+
}
72+
}

0 commit comments

Comments
 (0)