Skip to content

Commit 4eebd6c

Browse files
author
hosonishi
committed
BatchUpdateExecutor, BatchDeleteExecutor, MapBatchInsertBuilder を追加
1 parent 9dd2bff commit 4eebd6c

15 files changed

+1816
-297
lines changed
Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
/*
2+
* Copyright 2004-2010 the Seasar Foundation and the Others.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13+
* either express or implied. See the License for the specific language
14+
* governing permissions and limitations under the License.
15+
*/
16+
package org.seasar.doma.jdbc.builder;
17+
18+
import java.util.function.Function;
19+
import java.util.Map;
20+
import java.util.HashMap;
21+
import java.util.List;
22+
23+
import org.seasar.doma.DomaNullPointerException;
24+
import org.seasar.doma.jdbc.JdbcException;
25+
import org.seasar.doma.jdbc.Sql;
26+
import org.seasar.doma.jdbc.SqlLogType;
27+
import org.seasar.doma.jdbc.command.BatchModifyCommand;
28+
import org.seasar.doma.jdbc.query.SqlBatchModifyQuery;
29+
import org.seasar.doma.message.Message;
30+
31+
/**
32+
* バッチ更新で利用される、SQL文を組み立てるクラスです。
33+
*
34+
* @author bakenezumi
35+
* @since 2.14.0
36+
*/
37+
public abstract class BatchBuilder<Q extends SqlBatchModifyQuery> {
38+
39+
final BatchBuildingHelper helper;
40+
41+
final Q query;
42+
43+
final ParamIndex paramIndex;
44+
45+
final Map<Integer, String> paramNameMap;
46+
47+
BatchBuilder(Q query) {
48+
this.helper = new BatchBuildingHelper();
49+
this.query = query;
50+
this.paramIndex = new ParamIndex();
51+
paramNameMap = new HashMap<>();
52+
}
53+
54+
BatchBuilder(BatchBuildingHelper builder, Q query,
55+
ParamIndex paramIndex, Map<Integer, String> paramNameMap) {
56+
this.helper = builder;
57+
this.query = query;
58+
this.paramIndex = paramIndex;
59+
this.paramNameMap = paramNameMap;
60+
}
61+
62+
static BatchBuilder newInstance(SqlBatchModifyQuery query) {
63+
if (query == null) {
64+
throw new DomaNullPointerException("query");
65+
}
66+
if (query.getClassName() == null) {
67+
query.setCallerClassName(BatchBuilder.class.getName());
68+
}
69+
return new InitialBatchBuilder(query);
70+
}
71+
72+
/**
73+
* SQLの断片を追加します。
74+
*
75+
* @param sql
76+
* SQLの断片
77+
* @return このインスタンス
78+
* @throws DomaNullPointerException
79+
* 引数が {@code null} の場合
80+
*/
81+
public abstract BatchBuilder sql(String sql);
82+
83+
/**
84+
* 最後に追加したSQLもしくはパラメータを削除します。
85+
*
86+
* @return このインスタンス
87+
*/
88+
public abstract BatchBuilder removeLast();
89+
90+
/**
91+
* パラメータを追加します。
92+
* <p>
93+
* パラメータの型には、基本型とドメインクラスを指定できます。
94+
*
95+
* @param <P>
96+
* パラメータの型
97+
* @param paramClass
98+
* パラメータの要素のクラス
99+
* @param param
100+
* パラメータ
101+
* @return このインスタンス
102+
* @throws DomaNullPointerException
103+
* {@code paramClass} が {@code null} の場合
104+
*/
105+
public <P> BatchBuilder param(Class<P> paramClass, P param) {
106+
if (paramClass == null) {
107+
throw new DomaNullPointerException("paramClass");
108+
}
109+
return appendParam(paramClass, param, false);
110+
}
111+
112+
/**
113+
* リテラルとしてパラメータを追加します。
114+
* <p>
115+
* パラメータの型には、基本型とドメインクラスを指定できます。
116+
*
117+
* @param <P>
118+
* パラメータの型
119+
* @param paramClass
120+
* パラメータのクラス
121+
* @param param
122+
* パラメータ
123+
* @return このインスタンス
124+
* @throws DomaNullPointerException
125+
* {@code paramClass} が {@code null} の場合
126+
*/
127+
public <P> BatchBuilder literal(Class<P> paramClass, P param) {
128+
if (paramClass == null) {
129+
throw new DomaNullPointerException("paramClass");
130+
}
131+
return appendParam(paramClass, param, true);
132+
}
133+
134+
abstract <P> BatchBuilder appendParam(Class<P> paramClass, P param, boolean literal);
135+
136+
BatchBuilder fixSql() {
137+
return new FixedBatchBuilder(helper, query, paramNameMap);
138+
}
139+
140+
private void prepare() {
141+
query.clearParameters();
142+
for (BatchParam p : helper.getParams()) {
143+
query.addParameter(p.name, p.paramClass, p.params);
144+
}
145+
query.setSqlNode(helper.getSqlNode());
146+
query.prepare();
147+
}
148+
149+
int[] execute(Function<Q, BatchModifyCommand> commandBuilder) {
150+
if (query.getMethodName() == null) {
151+
query.setCallerMethodName("execute");
152+
}
153+
prepare();
154+
BatchModifyCommand command = commandBuilder.apply(query);
155+
int[] result = command.execute();
156+
query.complete();
157+
return result;
158+
}
159+
160+
List<? extends Sql<?>> getSqls() {
161+
if (query.getMethodName() == null) {
162+
query.setCallerMethodName("getSqls");
163+
}
164+
prepare();
165+
return query.getSqls();
166+
}
167+
168+
private static class InitialBatchBuilder<Q extends SqlBatchModifyQuery> extends BatchBuilder<Q> {
169+
170+
private InitialBatchBuilder(Q query) {
171+
super(query);
172+
}
173+
174+
private InitialBatchBuilder(BatchBuildingHelper builder, Q query,
175+
ParamIndex paramIndex, Map<Integer, String> paramNameMap) {
176+
super(builder, query, paramIndex, paramNameMap);
177+
}
178+
179+
@Override
180+
public BatchBuilder sql(String sql) {
181+
if (sql == null) {
182+
throw new DomaNullPointerException("sql");
183+
}
184+
helper.appendSqlWithLineSeparator(sql);
185+
return new SubsequentBatchBuilder(helper, query, paramIndex, paramNameMap);
186+
}
187+
188+
@Override
189+
public BatchBuilder removeLast() {
190+
helper.removeLast();
191+
return new SubsequentBatchBuilder(helper, query, paramIndex, paramNameMap);
192+
}
193+
194+
@Override
195+
<P> BatchBuilder appendParam(Class<P> paramClass, P param, boolean literal) {
196+
BatchParam batchParam = new BatchParam(paramClass, paramIndex, literal);
197+
batchParam.add(param);
198+
helper.appendParam(batchParam);
199+
paramNameMap.put(paramIndex.getValue(), batchParam.name);
200+
paramIndex.increment();
201+
return new SubsequentBatchBuilder(helper, query, paramIndex, paramNameMap);
202+
}
203+
204+
}
205+
206+
private static class SubsequentBatchBuilder<Q extends SqlBatchModifyQuery> extends InitialBatchBuilder<Q> {
207+
208+
SubsequentBatchBuilder(BatchBuildingHelper builder,
209+
Q query, ParamIndex paramIndex,
210+
Map<Integer, String> paramNameMap) {
211+
super(builder, query, paramIndex, paramNameMap);
212+
}
213+
214+
@Override
215+
public BatchBuilder sql(String sql) {
216+
if (sql == null) {
217+
throw new DomaNullPointerException("sql");
218+
}
219+
super.helper.appendSql(sql);
220+
return this;
221+
}
222+
}
223+
224+
private static class FixedBatchBuilder<Q extends SqlBatchModifyQuery> extends BatchBuilder<Q> {
225+
226+
private FixedBatchBuilder(BatchBuildingHelper builder, Q query, Map<Integer, String> paramNameMap) {
227+
super(builder, query, new ParamIndex(), paramNameMap);
228+
}
229+
230+
@Override
231+
public BatchBuilder sql(String sql) {
232+
return this;
233+
}
234+
235+
@Override
236+
public BatchBuilder removeLast() {
237+
return this;
238+
}
239+
240+
@Override
241+
<P> BatchBuilder appendParam(Class<P> paramClass, P param, boolean literal) {
242+
final String paramName = paramNameMap.get(paramIndex.getValue());
243+
if (paramName == null) {
244+
throw new JdbcException(Message.DOMA2231);
245+
}
246+
BatchParam batchParam = helper.getParam(paramName);
247+
if (paramClass != batchParam.paramClass) {
248+
// BatchParamの初期値が型:Object、値:nullの場合に限り型の上書きを許可
249+
if (batchParam.paramClass == Object.class) {
250+
batchParam = new BatchParam(batchParam, paramClass);
251+
helper.modifyParam(batchParam);
252+
} else if (param != null || paramClass != Object.class) {
253+
// 型違いは型:Object、値:nullの場合のみ許可
254+
throw new JdbcException(Message.DOMA2229);
255+
}
256+
}
257+
if (literal != batchParam.literal) {
258+
throw new JdbcException(Message.DOMA2230);
259+
}
260+
batchParam.add(param);
261+
paramIndex.increment();
262+
return this;
263+
}
264+
265+
}
266+
267+
}

src/main/java/org/seasar/doma/jdbc/builder/BatchBuildingHelper.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818
import static org.seasar.doma.internal.util.AssertionUtil.assertUnreachable;
1919

2020
import java.util.ArrayList;
21+
import java.util.HashMap;
2122
import java.util.LinkedList;
2223
import java.util.List;
24+
import java.util.Map;
2325

2426
import org.seasar.doma.internal.jdbc.sql.SqlParser;
2527
import org.seasar.doma.jdbc.SqlNode;
@@ -33,7 +35,8 @@ class BatchBuildingHelper {
3335
private static final String lineSeparator = System
3436
.getProperty("line.separator");
3537

36-
private final LinkedList<Item> items = new LinkedList<Item>();
38+
private final LinkedList<Item> items = new LinkedList<>();
39+
private final Map<String, Integer> paramIndexMap = new HashMap<>();
3740

3841
BatchBuildingHelper() {
3942
}
@@ -51,15 +54,25 @@ void appendSqlWithLineSeparator(String sql) {
5154
}
5255

5356
void appendParam(BatchParam param) {
57+
paramIndexMap.put(param.name, items.size());
5458
items.add(Item.param(param));
5559
}
5660

61+
void modifyParam(BatchParam param) {
62+
int index = paramIndexMap.get(param.name);
63+
items.set(index, Item.param(param));
64+
}
65+
5766
void removeLast() {
5867
if (!items.isEmpty()) {
5968
items.removeLast();
6069
}
6170
}
6271

72+
BatchParam getParam(String paramName) {
73+
return items.get(paramIndexMap.get(paramName)).param;
74+
}
75+
6376
List<BatchParam> getParams() {
6477
List<BatchParam> results = new ArrayList<BatchParam>();
6578
for (Item item : items) {

0 commit comments

Comments
 (0)