Skip to content

Commit 583429d

Browse files
authored
Merge pull request #183 from bakenezumi/batchBuilder2
BatchUpdateExecutor, BatchDeleteExecutor, MapBatchInsertBuilder を追加
2 parents 8b3fe2c + 90eccc1 commit 583429d

17 files changed

+1872
-310
lines changed
Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
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.Supplier;
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 {
38+
39+
final BatchBuildingHelper helper;
40+
41+
final SqlBatchModifyQuery query;
42+
43+
final ParamIndex paramIndex;
44+
45+
final Map<Integer, String> paramNameMap;
46+
47+
BatchBuilder(SqlBatchModifyQuery 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, SqlBatchModifyQuery 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(Supplier<BatchModifyCommand> commandFactory) {
150+
if (query.getMethodName() == null) {
151+
query.setCallerMethodName("execute");
152+
}
153+
prepare();
154+
BatchModifyCommand command = commandFactory.get();
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 extends BatchBuilder {
169+
170+
private InitialBatchBuilder(SqlBatchModifyQuery query) {
171+
super(query);
172+
}
173+
174+
private InitialBatchBuilder(BatchBuildingHelper builder, SqlBatchModifyQuery 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<P> 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 extends InitialBatchBuilder {
207+
208+
SubsequentBatchBuilder(BatchBuildingHelper builder,
209+
SqlBatchModifyQuery 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 extends BatchBuilder {
225+
226+
private FixedBatchBuilder(BatchBuildingHelper builder, SqlBatchModifyQuery 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 extends Object> 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+
final BatchParam<?> batchParam = helper.getParam(paramName);
247+
248+
if (literal != batchParam.literal) {
249+
throw new JdbcException(Message.DOMA2230);
250+
}
251+
if (paramClass != batchParam.paramClass) {
252+
// BatchParamの初期値が型:Object、値:nullの場合に限り型を上書き
253+
if (batchParam.paramClass == Object.class) {
254+
final BatchParam<P> newBatchParam = new BatchParam<P>(batchParam, paramClass);
255+
newBatchParam.add(param);
256+
helper.modifyParam(newBatchParam);
257+
} else if (param == null && paramClass == Object.class) {
258+
// 型違いは型:Object、値:nullの場合のみ許可
259+
batchParam.add(null);
260+
} else {
261+
throw new JdbcException(Message.DOMA2229);
262+
}
263+
} else {
264+
// paramClass == batchParam.paramClass であるため下記キャストは常に安全
265+
@SuppressWarnings("unchecked")
266+
final BatchParam<P> castedBatchParam = (BatchParam<P>) batchParam;
267+
castedBatchParam.add(param);
268+
}
269+
paramIndex.increment();
270+
return this;
271+
}
272+
273+
}
274+
275+
}

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

Lines changed: 19 additions & 6 deletions
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
}
@@ -50,18 +53,28 @@ void appendSqlWithLineSeparator(String sql) {
5053
}
5154
}
5255

53-
void appendParam(BatchParam param) {
56+
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

63-
List<BatchParam> getParams() {
64-
List<BatchParam> results = new ArrayList<BatchParam>();
72+
BatchParam<?> getParam(String paramName) {
73+
return items.get(paramIndexMap.get(paramName)).param;
74+
}
75+
76+
Iterable<BatchParam<?>> getParams() {
77+
List<BatchParam<?>> results = new ArrayList<>();
6578
for (Item item : items) {
6679
if (item.kind == ItemKind.PARAM) {
6780
results.add(item.param);
@@ -100,7 +113,7 @@ private static class Item {
100113

101114
private String sql;
102115

103-
private BatchParam param;
116+
private BatchParam<?> param;
104117

105118
public static Item sql(String sql) {
106119
Item item = new Item();
@@ -109,7 +122,7 @@ public static Item sql(String sql) {
109122
return item;
110123
}
111124

112-
public static Item param(BatchParam param) {
125+
public static Item param(BatchParam<?> param) {
113126
Item item = new Item();
114127
item.kind = ItemKind.PARAM;
115128
item.param = param;

0 commit comments

Comments
 (0)