1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.skife.jdbi.v2;
18
19 import org.skife.jdbi.v2.exceptions.UnableToCreateStatementException;
20 import org.skife.jdbi.v2.exceptions.UnableToExecuteStatementException;
21 import org.skife.jdbi.v2.tweak.RewrittenStatement;
22 import org.skife.jdbi.v2.tweak.SQLLog;
23 import org.skife.jdbi.v2.tweak.StatementBuilder;
24 import org.skife.jdbi.v2.tweak.StatementLocator;
25 import org.skife.jdbi.v2.tweak.StatementRewriter;
26
27 import java.sql.Connection;
28 import java.sql.PreparedStatement;
29 import java.sql.SQLException;
30 import java.util.ArrayList;
31 import java.util.List;
32 import java.util.Map;
33
34
35
36
37
38
39
40 public class PreparedBatch
41 {
42 private List<PreparedBatchPart> parts = new ArrayList<PreparedBatchPart>();
43 private final StatementLocator locator;
44 private final StatementRewriter rewriter;
45 private final Connection connection;
46 private final StatementBuilder preparedStatementCache;
47 private final String sql;
48 private final SQLLog log;
49 private final TimingCollector timingCollector;
50 private final StatementContext context;
51
52 PreparedBatch(StatementLocator locator,
53 StatementRewriter rewriter,
54 Connection connection,
55 StatementBuilder preparedStatementCache,
56 String sql,
57 Map<String, Object> globalStatementAttributes,
58 SQLLog log,
59 TimingCollector timingCollector)
60 {
61 this.locator = locator;
62 this.rewriter = rewriter;
63 this.connection = connection;
64 this.preparedStatementCache = preparedStatementCache;
65 this.sql = sql;
66 this.log = log;
67 this.timingCollector = timingCollector;
68 this.context = new StatementContext(globalStatementAttributes);
69 }
70
71
72
73
74
75
76 public PreparedBatch define(String key, Object value)
77 {
78 context.setAttribute(key, value);
79 return this;
80 }
81
82
83
84
85
86
87 public int[] execute()
88 {
89
90 if (parts.size() == 0) return new int[]{};
91
92 PreparedBatchPart current = parts.get(0);
93 final String my_sql ;
94 try {
95 my_sql = locator.locate(sql, context);
96 }
97 catch (Exception e) {
98 throw new UnableToCreateStatementException(String.format("Exception while locating statement for [%s]",
99 sql), e, context);
100 }
101 final RewrittenStatement rewritten = rewriter.rewrite(my_sql, current.getParameters(), context);
102 PreparedStatement stmt = null;
103 try {
104 try {
105 stmt = connection.prepareStatement(rewritten.getSql());
106 }
107 catch (SQLException e) {
108 throw new UnableToCreateStatementException(e, context);
109 }
110
111 try {
112 for (PreparedBatchPart part : parts) {
113 rewritten.bind(part.getParameters(), stmt);
114 stmt.addBatch();
115 }
116 }
117 catch (SQLException e) {
118 throw new UnableToExecuteStatementException("Exception while binding parameters", e, context);
119 }
120
121 try {
122 final long start = System.nanoTime();
123 final int[] rs = stmt.executeBatch();
124 final long elapsedTime = (System.nanoTime() - start);
125 log.logPreparedBatch(elapsedTime / 1000000L, rewritten.getSql(), parts.size());
126 timingCollector.collect(elapsedTime, context);
127 return rs;
128 }
129 catch (SQLException e) {
130 throw new UnableToExecuteStatementException(e, context);
131 }
132 }
133 finally {
134 QueryPostMungeCleanup.CLOSE_RESOURCES_QUIETLY.cleanup(null, stmt, null);
135 this.parts.clear();
136 }
137 }
138
139
140
141
142
143
144
145 public PreparedBatchPart add()
146 {
147 PreparedBatchPart part = new PreparedBatchPart(this, locator, rewriter, connection, preparedStatementCache, sql, context, log, timingCollector);
148 parts.add(part);
149 return part;
150 }
151
152 public PreparedBatch add(Object... args)
153 {
154 PreparedBatchPart part = new PreparedBatchPart(this, locator, rewriter, connection, preparedStatementCache, sql, context, log, timingCollector);
155
156 for (int i = 0; i < args.length; ++i) {
157 part.bind(i, args[i]);
158 }
159
160 parts.add(part);
161
162 return this;
163 }
164
165
166
167
168
169
170
171
172
173
174 public PreparedBatchPart add(Map<String, ? extends Object> args)
175 {
176 PreparedBatchPart part = new PreparedBatchPart(this, locator, rewriter, connection, preparedStatementCache, sql, context, log, timingCollector);
177 parts.add(part);
178 part.bindFromMap(args);
179 return part;
180 }
181
182
183
184
185 public int getSize()
186 {
187 return parts.size();
188 }
189
190
191
192
193 public int size()
194 {
195 return parts.size();
196 }
197 }