全てを再実装したJdbcAcsessです。
Revision | f27c15389a605704d5dc61da8d74f9f55b4a00f6 (tree) |
---|---|
Time | 2012-03-03 21:57:38 |
Author | shimakazuro |
Commiter | shimakazuro |
mousewheelでfont変更
@@ -615,6 +615,7 @@ | ||
615 | 615 | Font font = jTable.getFont(); |
616 | 616 | jTable.setFont(new Font(Font.MONOSPACED, font.getStyle(), font.getSize())); |
617 | 617 | |
618 | + new FontZoomByMouseWheel(jTable); | |
618 | 619 | resultsTableColumnFit = new TableColumnFit(jTable); |
619 | 620 | jTable.setModel(new ResultsTableModel()); |
620 | 621 | } |
@@ -1,15 +1,15 @@ | ||
1 | 1 | /* |
2 | 2 | * Copyright 2011 Kazuhiro Shimada |
3 | 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. | |
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 | 6 | * You may obtain a copy of the License at |
7 | 7 | * |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | 9 | * |
10 | - * Unless required by applicable law or agreed to in writing, software | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
@@ -40,9 +40,6 @@ | ||
40 | 40 | |
41 | 41 | private static final long serialVersionUID = -7507194043135028576L; |
42 | 42 | |
43 | - /** | |
44 | - * | |
45 | - */ | |
46 | 43 | public JmyTable() { |
47 | 44 | super(); |
48 | 45 | initialize(); |
@@ -112,6 +109,7 @@ | ||
112 | 109 | setRowSelectionAllowed(true); |
113 | 110 | setAutoCreateRowSorter(true); |
114 | 111 | setEditable(false); |
112 | + new FontZoomByMouseWheel(this); | |
115 | 113 | } |
116 | 114 | |
117 | 115 | @Override |
@@ -172,7 +170,7 @@ | ||
172 | 170 | /** |
173 | 171 | * 追加変更削除が行われた行を選択する。 |
174 | 172 | */ |
175 | - private TableModelListener tableModelListener = new TableModelListener() { | |
173 | + private final TableModelListener tableModelListener = new TableModelListener() { | |
176 | 174 | @Override |
177 | 175 | public void tableChanged(TableModelEvent event) { |
178 | 176 |
@@ -221,4 +219,5 @@ | ||
221 | 219 | } |
222 | 220 | } |
223 | 221 | }; |
222 | + | |
224 | 223 | } |
@@ -39,7 +39,6 @@ | ||
39 | 39 | import java.util.Properties; |
40 | 40 | import java.util.StringTokenizer; |
41 | 41 | import java.util.concurrent.Callable; |
42 | -import java.util.concurrent.CopyOnWriteArrayList; | |
43 | 42 | import java.util.concurrent.ExecutionException; |
44 | 43 | import java.util.concurrent.ExecutorService; |
45 | 44 | import java.util.concurrent.Executors; |
@@ -47,6 +46,8 @@ | ||
47 | 46 | import java.util.concurrent.TimeoutException; |
48 | 47 | import java.util.logging.Level; |
49 | 48 | |
49 | +import javax.swing.event.EventListenerList; | |
50 | + | |
50 | 51 | import jdbcacsess2.main.Jdbcacsess2; |
51 | 52 | import jdbcacsess2.sqlService.exception.DbConnectAlreadyException; |
52 | 53 | import jdbcacsess2.sqlService.exception.DbConnectDriverLoadException; |
@@ -82,18 +83,10 @@ | ||
82 | 83 | private String connectName; |
83 | 84 | |
84 | 85 | /** |
85 | - * Connection の open/close等のコネクション状態変更を通知するリスナーリスト リスナーの通知呼び出し中に、@ | |
86 | - * {@link DataBaseConnection#removeConnectionlisteners(DataBaseConnectionListener)} | |
87 | - * が呼ばても良い様に {@link CopyOnWriteArrayList}を使用する。 | |
86 | + * Connection の open/close等のコネクション状態変更またはトランザクションの開始、AutoCommitの状態変更 | |
87 | + * を通知するリスナーリスト | |
88 | 88 | */ |
89 | - private final List<DataBaseConnectionListener> connectionListeners = new CopyOnWriteArrayList<DataBaseConnectionListener>(); | |
90 | - | |
91 | - /** | |
92 | - * トランザクションの開始、AutoCommitの状態変更 を通知するリスナーリスト リスナーの通知呼び出し中に、@ | |
93 | - * {@link DataBaseConnection#removeTransactionlisteners(DataBaseTransactionListener)} | |
94 | - * が呼ばても良い様に {@link CopyOnWriteArrayList}を使用する。 | |
95 | - */ | |
96 | - private final List<DataBaseTransactionListener> transactionListeners = new CopyOnWriteArrayList<DataBaseTransactionListener>(); | |
89 | + private final EventListenerList listeners = new EventListenerList(); | |
97 | 90 | |
98 | 91 | /** |
99 | 92 | * connectionの使用中であるか |
@@ -152,20 +145,14 @@ | ||
152 | 145 | * @param listener |
153 | 146 | */ |
154 | 147 | public void addConnectionListener(DataBaseConnectionListener listener) { |
155 | - if (listener == null) { | |
156 | - throw new NullPointerException(); | |
157 | - } | |
158 | - connectionListeners.add(listener); | |
148 | + listeners.add(DataBaseConnectionListener.class, listener); | |
159 | 149 | } |
160 | 150 | |
161 | 151 | /** |
162 | 152 | * 接続開始・終了リスナーの解除 |
163 | 153 | */ |
164 | 154 | public void removeConnectionlisteners(DataBaseConnectionListener listener) { |
165 | - if (listener == null) { | |
166 | - throw new NullPointerException(); | |
167 | - } | |
168 | - connectionListeners.remove(listener); | |
155 | + listeners.remove(DataBaseConnectionListener.class, listener); | |
169 | 156 | } |
170 | 157 | |
171 | 158 | /** |
@@ -174,20 +161,14 @@ | ||
174 | 161 | * @param listener |
175 | 162 | */ |
176 | 163 | public void addTransactionListener(DataBaseTransactionListener listener) { |
177 | - if (listener == null) { | |
178 | - throw new NullPointerException(); | |
179 | - } | |
180 | - transactionListeners.add(listener); | |
164 | + listeners.add(DataBaseTransactionListener.class, listener); | |
181 | 165 | } |
182 | 166 | |
183 | 167 | /** |
184 | 168 | * トランザクション終了リスナーの解除 |
185 | 169 | */ |
186 | 170 | public void removeTransactionlisteners(DataBaseTransactionListener listener) { |
187 | - if (listener == null) { | |
188 | - throw new NullPointerException(); | |
189 | - } | |
190 | - transactionListeners.remove(listener); | |
171 | + listeners.remove(DataBaseTransactionListener.class, listener); | |
191 | 172 | } |
192 | 173 | |
193 | 174 | /** |
@@ -303,7 +284,7 @@ | ||
303 | 284 | |
304 | 285 | executorService = Executors.newSingleThreadExecutor(); |
305 | 286 | |
306 | - for (DataBaseConnectionListener listener : connectionListeners) { | |
287 | + for (DataBaseConnectionListener listener : listeners.getListeners(DataBaseConnectionListener.class)) { | |
307 | 288 | Jdbcacsess2.logger.fine("***opened***" + " " + listener.toString()); |
308 | 289 | listener.dataBaseConnectionOpened(this); |
309 | 290 | } |
@@ -352,7 +333,7 @@ | ||
352 | 333 | * SQL実行中の場合 |
353 | 334 | */ |
354 | 335 | public void close() throws DbConnectIllgalStateException { |
355 | - for (DataBaseConnectionListener listener : connectionListeners) { | |
336 | + for (DataBaseConnectionListener listener : listeners.getListeners(DataBaseConnectionListener.class)) { | |
356 | 337 | Jdbcacsess2.logger.fine("***closing***" + " " + listener.toString()); |
357 | 338 | listener.dataBaseConnectionClosing(this); |
358 | 339 | } |
@@ -376,7 +357,7 @@ | ||
376 | 357 | }).get(TIMEOUT_SECONDS, TimeUnit.SECONDS); |
377 | 358 | |
378 | 359 | // CLOSEが成功したときだけ通知する。 |
379 | - for (DataBaseConnectionListener listener : connectionListeners) { | |
360 | + for (DataBaseConnectionListener listener : listeners.getListeners(DataBaseConnectionListener.class)) { | |
380 | 361 | Jdbcacsess2.logger.fine("***closed***" + " " + listener.toString()); |
381 | 362 | listener.dataBaseConnectionClosed(this); |
382 | 363 | } |
@@ -435,7 +416,7 @@ | ||
435 | 416 | }).get(TIMEOUT_SECONDS, TimeUnit.SECONDS); |
436 | 417 | |
437 | 418 | // 成功したときだけ通知する。 |
438 | - for (DataBaseTransactionListener listener : transactionListeners) { | |
419 | + for (DataBaseTransactionListener listener : listeners.getListeners(DataBaseTransactionListener.class)) { | |
439 | 420 | listener.commitEnd(this); |
440 | 421 | } |
441 | 422 |
@@ -462,7 +443,7 @@ | ||
462 | 443 | }).get(TIMEOUT_SECONDS, TimeUnit.SECONDS); |
463 | 444 | |
464 | 445 | // 成功したときだけ通知する。 |
465 | - for (DataBaseTransactionListener listener : transactionListeners) { | |
446 | + for (DataBaseTransactionListener listener : listeners.getListeners(DataBaseTransactionListener.class)) { | |
466 | 447 | listener.rollbackEnd(this); |
467 | 448 | } |
468 | 449 |
@@ -504,7 +485,7 @@ | ||
504 | 485 | }).get(TIMEOUT_SECONDS, TimeUnit.SECONDS); |
505 | 486 | |
506 | 487 | // 成功したときだけ通知する。 |
507 | - for (DataBaseTransactionListener listener : transactionListeners) { | |
488 | + for (DataBaseTransactionListener listener : listeners.getListeners(DataBaseTransactionListener.class)) { | |
508 | 489 | listener.autoCommitChange(this, autoCommit); |
509 | 490 | } |
510 | 491 |
@@ -1,27 +1,29 @@ | ||
1 | 1 | /* |
2 | 2 | * Copyright 2011 Kazuhiro Shimada |
3 | 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. | |
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 | 6 | * You may obtain a copy of the License at |
7 | 7 | * |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | 9 | * |
10 | - * Unless required by applicable law or agreed to in writing, software | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | 16 | package jdbcacsess2.sqlService; |
17 | 17 | |
18 | +import java.util.EventListener; | |
19 | + | |
18 | 20 | /** |
19 | 21 | * DataBaseConnectionに関するリスナーのマーカクラス |
20 | 22 | * |
21 | 23 | * @author sima |
22 | 24 | * |
23 | 25 | */ |
24 | -public interface DataBaseListener { | |
26 | +public interface DataBaseListener extends EventListener { | |
25 | 27 | |
26 | 28 | |
27 | 29 | } |
@@ -19,7 +19,6 @@ | ||
19 | 19 | import java.sql.ResultSet; |
20 | 20 | import java.sql.SQLException; |
21 | 21 | import java.util.ArrayList; |
22 | -import java.util.Collections; | |
23 | 22 | import java.util.List; |
24 | 23 | import java.util.concurrent.Callable; |
25 | 24 | import java.util.concurrent.ExecutionException; |
@@ -28,6 +27,8 @@ | ||
28 | 27 | import java.util.concurrent.TimeoutException; |
29 | 28 | import java.util.logging.Level; |
30 | 29 | |
30 | +import javax.swing.event.EventListenerList; | |
31 | + | |
31 | 32 | import jdbcacsess2.main.Jdbcacsess2; |
32 | 33 | import jdbcacsess2.main.ShowDialog; |
33 | 34 | import jdbcacsess2.sqlService.SqlExecuteParmeter.Parameter; |
@@ -55,7 +56,7 @@ | ||
55 | 56 | /** |
56 | 57 | * 処理結果通知リスナーのリスト |
57 | 58 | */ |
58 | - private final List<SqlExecutedListener> sqlExecutedListeners; | |
59 | + private final EventListenerList sqlExecutedListeners; | |
59 | 60 | /** |
60 | 61 | * 実行中のスレッド |
61 | 62 | */ |
@@ -70,7 +71,7 @@ | ||
70 | 71 | */ |
71 | 72 | public SqlAsyncExecute(String sqlSentence, String sentenceSeparator) { |
72 | 73 | |
73 | - sqlExecutedListeners = Collections.synchronizedList(new ArrayList<SqlExecutedListener>()); | |
74 | + sqlExecutedListeners = new EventListenerList(); | |
74 | 75 | |
75 | 76 | sqlExecuteSentenceList = new SqlExecuteSentencies(sqlSentence, sentenceSeparator).getSqlExecuteSentenceList(); |
76 | 77 | } |
@@ -127,27 +128,14 @@ | ||
127 | 128 | * @param listener |
128 | 129 | */ |
129 | 130 | public void addSqlExcutedListener(SqlExecutedListener listener) { |
130 | - if (listener == null) { | |
131 | - throw new NullPointerException(); | |
132 | - } | |
133 | - sqlExecutedListeners.add(listener); | |
131 | + sqlExecutedListeners.add(SqlExecutedListener.class, listener); | |
134 | 132 | } |
135 | 133 | |
136 | 134 | /** |
137 | 135 | * 結果受け取りリスナーの削除 |
138 | 136 | */ |
139 | 137 | public void removeSqlExcutedListener(SqlExecutedListener listener) { |
140 | - if (listener == null) { | |
141 | - throw new NullPointerException(); | |
142 | - } | |
143 | - sqlExecutedListeners.remove(listener); | |
144 | - } | |
145 | - | |
146 | - /** | |
147 | - * 結果受け取りリスナーの全削除 | |
148 | - */ | |
149 | - public void removeAllSqlExcutedListener() { | |
150 | - sqlExecutedListeners.clear(); | |
138 | + sqlExecutedListeners.remove(SqlExecutedListener.class, listener); | |
151 | 139 | } |
152 | 140 | |
153 | 141 | /** |
@@ -170,7 +158,7 @@ | ||
170 | 158 | SqlTask sqlTask = new SqlTask(dataBaseConnection); |
171 | 159 | thread = new Thread(sqlTask); |
172 | 160 | thread.start(); |
173 | - for (SqlExecutedListener l : sqlExecutedListeners) { | |
161 | + for (SqlExecutedListener l : sqlExecutedListeners.getListeners(SqlExecutedListener.class)) { | |
174 | 162 | l.taskAccept(sqlTask); |
175 | 163 | } |
176 | 164 | Jdbcacsess2.logger.fine("(execute) return."); |
@@ -238,287 +226,287 @@ | ||
238 | 226 | /** |
239 | 227 | * コンストラクタ。 |
240 | 228 | */ |
241 | - public SqlTask(DataBaseConnection dataBaseConnection) { | |
242 | - this.dataBaseConnection = dataBaseConnection; | |
243 | - } | |
244 | - | |
245 | - /** | |
246 | - * スレッド実行メソッド | |
247 | - */ | |
248 | - public void run() { | |
249 | - Jdbcacsess2.logger.info("(task)beging."); | |
250 | - | |
251 | - // コネクションクローズ時に、スレッドの後始末を自動的に行う為、リスナー登録 | |
252 | - dataBaseConnection.addConnectionListener(changeConnection); | |
253 | - | |
254 | - for (SqlExecuteSentence sentence : sqlExecuteSentenceList) { | |
255 | - if (Thread.interrupted()) { | |
256 | - Jdbcacsess2.logger.info(" (task)canceled."); | |
257 | - break; | |
258 | - } | |
259 | - sqlExec(sentence); | |
260 | - } | |
261 | - | |
262 | - // 全てのSQLが終了した時にロックを開放する | |
263 | - try { | |
264 | - dataBaseConnection.unlockConnection(); | |
265 | - } catch (DbConnectIllgalStateException e) { | |
266 | - // ありえない例外 | |
267 | - e.printStackTrace(); | |
268 | - throw new RuntimeException(e); | |
269 | - } | |
270 | - | |
271 | - // 後始末リスナーの削除 | |
272 | - dataBaseConnection.removeConnectionlisteners(changeConnection); | |
273 | - | |
274 | - for (SqlExecutedListener l : sqlExecutedListeners) { | |
275 | - l.executeAllEnd(); | |
276 | - } | |
277 | - } | |
278 | - | |
279 | - private void sqlExec(SqlExecuteSentence sqlExecuteSentence) { | |
280 | - sqlTaskThrow = null; | |
281 | - timeMillisThreadStart = System.currentTimeMillis(); | |
282 | - timeMillisThreadEnd = 0; | |
283 | - rowCnt = 0; | |
284 | - try { | |
285 | - Jdbcacsess2.logger.info(" (Statement)EXECSQL=[" + sqlExecuteSentence.getSqlSentence() + "]"); | |
286 | - for (SqlExecutedListener l : sqlExecutedListeners) { | |
287 | - l.executBegin(sqlExecuteSentence); | |
288 | - } | |
289 | - | |
290 | - if (sqlExecuteSentence.getSqlCommand().equals("CALL")) { | |
291 | - preparedStatement = dataBaseConnection.prepareCall(sqlExecuteSentence.getSqlSentence()); | |
292 | - } else { | |
293 | - preparedStatement = dataBaseConnection.prepareStatement(sqlExecuteSentence.getSqlSentence()); | |
294 | - } | |
295 | - | |
296 | - // パラメータ取り込み処理がfalseを返すまで繰り返す | |
297 | - SqlInputParameter sqlInputParameter = sqlExecuteSentence.getSqlInputParameter(); | |
298 | - | |
299 | - while (sqlInputParameter.getSqlExecuteParmeter().hasNext()) { | |
300 | - if (Thread.interrupted()) { | |
301 | - Jdbcacsess2.logger.info(" (task)canceled."); | |
302 | - break; | |
303 | - } | |
304 | - | |
305 | - // パラメータ設定を呼び出す | |
306 | - Parameter parameter = sqlInputParameter.getSqlExecuteParmeter().getParameter(); | |
307 | - | |
308 | - // preparedStatementのパラメータ設定 | |
309 | - setParameters(sqlInputParameter.getInputItemNames(), parameter); | |
310 | - | |
311 | - // SQL実行し、結果により受け取る方法を振り分ける | |
312 | - if (preparedStatement.execute()) { | |
313 | - readResultSet(); | |
314 | - } else { | |
315 | - rowCnt += preparedStatement.getUpdateCount(); | |
316 | - } | |
317 | - | |
318 | - } | |
319 | - | |
320 | - } catch (Throwable t) { | |
321 | - t.printStackTrace(); | |
322 | - sqlTaskThrow = t; | |
323 | - } finally { | |
324 | - try { | |
325 | - if (preparedStatement != null) { | |
326 | - preparedStatement.close(); | |
327 | - Jdbcacsess2.logger.info(" (task)Statement closed"); | |
328 | - } | |
329 | - } catch (SQLException e) { | |
330 | - Jdbcacsess2.logger.log(Level.WARNING, "WARNING", e); | |
331 | - } finally { | |
332 | - preparedStatement = null; | |
333 | - | |
334 | - timeMillisThreadEnd = System.currentTimeMillis(); | |
335 | - | |
336 | - if (sqlTaskThrow == null) { | |
337 | - for (SqlExecutedListener l : sqlExecutedListeners) { | |
338 | - l.executNormalFinish(rowCnt); | |
339 | - } | |
340 | - Jdbcacsess2.logger.info(" (task)noramal end. cnt=[" + rowCnt + "] " | |
341 | - + (timeMillisThreadEnd - timeMillisThreadStart) + "ms"); | |
342 | - } else { | |
343 | - for (SqlExecutedListener l : sqlExecutedListeners) { | |
344 | - l.executeException(sqlTaskThrow); | |
345 | - } | |
346 | - Jdbcacsess2.logger.info(" (task)abnormal end. cnt=[" + rowCnt + "] " | |
347 | - + (timeMillisThreadEnd - timeMillisThreadStart) + "ms"); | |
348 | - } | |
349 | - | |
350 | - } | |
351 | - } | |
352 | - } | |
353 | - | |
354 | - /** | |
355 | - * JDBCprepareステートメントのパラメータを設定する。 | |
356 | - * | |
357 | - * @param sqlInputItems | |
358 | - * パラメータ名称リスト | |
359 | - * @param p | |
360 | - * KEY=パラメータリストのインデックス/VALUE=SQL型 のマップ。 | |
361 | - */ | |
362 | - private void setParameters(ArrayList<String> sqlInputItems, Parameter p) | |
363 | - throws SQLException { | |
364 | - | |
365 | - Jdbcacsess2.logger.fine(" (setParameters)VALUES=" + p.values + "SQLTYPES=" + p.sqlTypes + ""); | |
366 | - | |
367 | - if (sqlInputItems.size() != p.values.size()) { | |
368 | - throw new IllegalArgumentException("入力パラ数が分析結果と不一致:" + "Input=" + p.values.size() + " analized=" | |
369 | - + sqlInputItems); | |
370 | - } | |
371 | - | |
372 | - for (int i = 0; i < p.values.size(); i++) { | |
373 | - Object o = p.values.get(i); | |
374 | - ConstSqlTypes constSqlTypes = p.sqlTypes.get(i); | |
229 | + public SqlTask(DataBaseConnection dataBaseConnection) { | |
230 | + this.dataBaseConnection = dataBaseConnection; | |
231 | + } | |
375 | 232 | |
376 | - if (constSqlTypes == null) { | |
377 | - preparedStatement.setObject(i + 1, o); | |
378 | - } else { | |
379 | - preparedStatement.setObject(i + 1, o, constSqlTypes.getValue()); | |
380 | - Jdbcacsess2.logger.fine(" (setParameters)" + constSqlTypes); | |
381 | - } | |
382 | - } | |
383 | - } | |
384 | - | |
385 | - /** | |
386 | - * 検索結果を取り出す | |
387 | - * | |
388 | - * @throws Throwable | |
389 | - */ | |
390 | - private void readResultSet() throws Throwable { | |
391 | - | |
392 | - ResultSet resultSet = preparedStatement.getResultSet(); | |
393 | - // getMetaData()は、getResultSet()を実行してから行う。 | |
394 | - // sqliteは、"IllegalStateException: SQLite JDBC: inconsistent internal state" | |
395 | - // 例外が発生する。 | |
396 | - List<ColumnAttributeResult> list = ColumnAttributeResult.convColumnAttributeResult(resultSet.getMetaData()); | |
397 | - | |
398 | - Jdbcacsess2.logger.info(" (task)resultSet opened."); | |
399 | - for (SqlExecutedListener l : sqlExecutedListeners) { | |
400 | - l.resultHeader(list); | |
401 | - } | |
402 | - | |
403 | - int columnCnt = list.size(); | |
404 | - | |
405 | - try { | |
406 | - while (resultSet.next()) { | |
407 | - synchronized (this) { | |
408 | - if (Thread.interrupted()) { | |
409 | - Jdbcacsess2.logger.info(" (task)canceled."); | |
410 | - break; | |
411 | - } | |
412 | - ArrayList<Object> results = new ArrayList<Object>(columnCnt); | |
413 | - for (int i = 1; i <= columnCnt; i++) { | |
414 | - results.add(resultSet.getObject(i)); | |
415 | - } | |
416 | - | |
417 | - rowCnt++; | |
418 | - for (SqlExecutedListener l : sqlExecutedListeners) { | |
419 | - l.resultDetail(rowCnt, results); | |
420 | - } | |
421 | - Jdbcacsess2.logger.finest(" (task)results notified."); | |
422 | - | |
423 | - if (rowCnt % resultRowLimitCnt == 0) { | |
424 | - | |
425 | - available = true; | |
426 | - new Thread() { | |
427 | - @Override | |
428 | - public void run() { | |
429 | - for (SqlExecutedListener l : sqlExecutedListeners) { | |
430 | - l.statusContinue(rowCnt); | |
431 | - } | |
432 | - } | |
433 | - }.start(); | |
434 | - Jdbcacsess2.logger.info(" (task)waiting."); | |
233 | + /** | |
234 | + * スレッド実行メソッド | |
235 | + */ | |
236 | + public void run() { | |
237 | + Jdbcacsess2.logger.info("(task)beging."); | |
435 | 238 | |
436 | - while (available) { | |
437 | - try { | |
438 | - wait(); | |
439 | - } catch (InterruptedException e) { | |
440 | - Jdbcacsess2.logger.fine(" (task)interrupted."); | |
441 | - // wait() により割り込みフラグがクリアされたので、 | |
442 | - // 自身にもう一度割り込みをかける。ループ脱出をを検知させる為。 | |
443 | - Thread.currentThread().interrupt(); | |
444 | - break; | |
445 | - } | |
446 | - } | |
447 | - Jdbcacsess2.logger.info(" (task)wake up."); | |
448 | - } | |
449 | - } | |
450 | - } | |
451 | - } catch (Throwable t) { | |
452 | - throw t; | |
453 | - } finally { | |
454 | - resultSet.close(); | |
455 | - Jdbcacsess2.logger.info(" (task)resultSet closed."); | |
456 | - } | |
457 | - } | |
458 | - | |
459 | - /** | |
460 | - * 待機中のSQL実行スレッドを再開する | |
461 | - */ | |
462 | - @Override | |
463 | - public void taskWakeUp() { | |
464 | - synchronized (this) { | |
465 | - available = false; | |
466 | - notifyAll(); | |
467 | - } | |
468 | - } | |
469 | - | |
470 | - /** | |
471 | - * 実行中のSQL実行スレッドを中止を要求する | |
472 | - */ | |
473 | - @Override | |
474 | - public void taskCancel() { | |
475 | - thread.interrupt(); | |
476 | - } | |
239 | + // コネクションクローズ時に、スレッドの後始末を自動的に行う為、リスナー登録 | |
240 | + dataBaseConnection.addConnectionListener(changeConnection); | |
477 | 241 | |
478 | - /** | |
479 | - * SQL実行スレッドの終了を待ち合わせる | |
480 | - */ | |
481 | - @Override | |
482 | - public void taskJoin(int timeoutSeconds) { | |
483 | - Jdbcacsess2.logger.info(" (join)joining..."); | |
484 | - try { | |
485 | - Executors.newSingleThreadExecutor().submit(new Callable<Object>() { | |
486 | - @Override | |
487 | - public Object call() throws Exception { | |
488 | - thread.join(); | |
489 | - return null; | |
490 | - } | |
491 | - }).get(timeoutSeconds, TimeUnit.SECONDS); | |
492 | - } catch (InterruptedException e) { | |
493 | - Jdbcacsess2.logger.log(Level.WARNING, "WARNING", e); | |
494 | - } catch (ExecutionException e) { | |
495 | - e.printStackTrace(); | |
496 | - } catch (TimeoutException e) { | |
497 | - ShowDialog.errorMessage(e); | |
498 | - } | |
499 | - Jdbcacsess2.logger.info(" (join)joined."); | |
500 | - } | |
242 | + for (SqlExecuteSentence sentence : sqlExecuteSentenceList) { | |
243 | + if (Thread.interrupted()) { | |
244 | + Jdbcacsess2.logger.info(" (task)canceled."); | |
245 | + break; | |
246 | + } | |
247 | + sqlExec(sentence); | |
248 | + } | |
501 | 249 | |
502 | - /** | |
503 | - * | |
504 | - * @return 処理時間 単位はミリ秒 | |
505 | - */ | |
506 | - @Override | |
507 | - public long getExecutionTime() { | |
508 | - if (timeMillisThreadStart == 0) { | |
509 | - return 0; | |
510 | - } | |
511 | - if (timeMillisThreadEnd == 0) { | |
512 | - return 0; | |
513 | - } | |
514 | - return timeMillisThreadEnd - timeMillisThreadStart; | |
515 | - } | |
250 | + // 全てのSQLが終了した時にロックを開放する | |
251 | + try { | |
252 | + dataBaseConnection.unlockConnection(); | |
253 | + } catch (DbConnectIllgalStateException e) { | |
254 | + // ありえない例外 | |
255 | + e.printStackTrace(); | |
256 | + throw new RuntimeException(e); | |
257 | + } | |
516 | 258 | |
517 | - @Override | |
518 | - public int getCnt() { | |
519 | - return sqlExecuteSentenceList.size(); | |
259 | + // 後始末リスナーの削除 | |
260 | + dataBaseConnection.removeConnectionlisteners(changeConnection); | |
520 | 261 | |
521 | - } | |
262 | + for (SqlExecutedListener l : sqlExecutedListeners.getListeners(SqlExecutedListener.class)) { | |
263 | + l.executeAllEnd(); | |
264 | + } | |
265 | + } | |
266 | + | |
267 | + private void sqlExec(SqlExecuteSentence sqlExecuteSentence) { | |
268 | + sqlTaskThrow = null; | |
269 | + timeMillisThreadStart = System.currentTimeMillis(); | |
270 | + timeMillisThreadEnd = 0; | |
271 | + rowCnt = 0; | |
272 | + try { | |
273 | + Jdbcacsess2.logger.info(" (Statement)EXECSQL=[" + sqlExecuteSentence.getSqlSentence() + "]"); | |
274 | + for (SqlExecutedListener l : sqlExecutedListeners.getListeners(SqlExecutedListener.class)) { | |
275 | + l.executBegin(sqlExecuteSentence); | |
276 | + } | |
277 | + | |
278 | + if (sqlExecuteSentence.getSqlCommand().equals("CALL")) { | |
279 | + preparedStatement = dataBaseConnection.prepareCall(sqlExecuteSentence.getSqlSentence()); | |
280 | + } else { | |
281 | + preparedStatement = dataBaseConnection.prepareStatement(sqlExecuteSentence.getSqlSentence()); | |
282 | + } | |
283 | + | |
284 | + // パラメータ取り込み処理がfalseを返すまで繰り返す | |
285 | + SqlInputParameter sqlInputParameter = sqlExecuteSentence.getSqlInputParameter(); | |
286 | + | |
287 | + while (sqlInputParameter.getSqlExecuteParmeter().hasNext()) { | |
288 | + if (Thread.interrupted()) { | |
289 | + Jdbcacsess2.logger.info(" (task)canceled."); | |
290 | + break; | |
291 | + } | |
292 | + | |
293 | + // パラメータ設定を呼び出す | |
294 | + Parameter parameter = sqlInputParameter.getSqlExecuteParmeter().getParameter(); | |
295 | + | |
296 | + // preparedStatementのパラメータ設定 | |
297 | + setParameters(sqlInputParameter.getInputItemNames(), parameter); | |
298 | + | |
299 | + // SQL実行し、結果により受け取る方法を振り分ける | |
300 | + if (preparedStatement.execute()) { | |
301 | + readResultSet(); | |
302 | + } else { | |
303 | + rowCnt += preparedStatement.getUpdateCount(); | |
304 | + } | |
305 | + | |
306 | + } | |
307 | + | |
308 | + } catch (Throwable t) { | |
309 | + t.printStackTrace(); | |
310 | + sqlTaskThrow = t; | |
311 | + } finally { | |
312 | + try { | |
313 | + if (preparedStatement != null) { | |
314 | + preparedStatement.close(); | |
315 | + Jdbcacsess2.logger.info(" (task)Statement closed"); | |
316 | + } | |
317 | + } catch (SQLException e) { | |
318 | + Jdbcacsess2.logger.log(Level.WARNING, "WARNING", e); | |
319 | + } finally { | |
320 | + preparedStatement = null; | |
321 | + | |
322 | + timeMillisThreadEnd = System.currentTimeMillis(); | |
323 | + | |
324 | + if (sqlTaskThrow == null) { | |
325 | + for (SqlExecutedListener l : sqlExecutedListeners.getListeners(SqlExecutedListener.class)) { | |
326 | + l.executNormalFinish(rowCnt); | |
327 | + } | |
328 | + Jdbcacsess2.logger.info(" (task)noramal end. cnt=[" + rowCnt + "] " | |
329 | + + (timeMillisThreadEnd - timeMillisThreadStart) + "ms"); | |
330 | + } else { | |
331 | + for (SqlExecutedListener l : sqlExecutedListeners.getListeners(SqlExecutedListener.class)) { | |
332 | + l.executeException(sqlTaskThrow); | |
333 | + } | |
334 | + Jdbcacsess2.logger.info(" (task)abnormal end. cnt=[" + rowCnt + "] " | |
335 | + + (timeMillisThreadEnd - timeMillisThreadStart) + "ms"); | |
336 | + } | |
337 | + | |
338 | + } | |
339 | + } | |
340 | + } | |
341 | + | |
342 | + /** | |
343 | + * JDBCprepareステートメントのパラメータを設定する。 | |
344 | + * | |
345 | + * @param sqlInputItems | |
346 | + * パラメータ名称リスト | |
347 | + * @param p | |
348 | + * KEY=パラメータリストのインデックス/VALUE=SQL型 のマップ。 | |
349 | + */ | |
350 | + private void setParameters(ArrayList<String> sqlInputItems, Parameter p) | |
351 | + throws SQLException { | |
352 | + | |
353 | + Jdbcacsess2.logger.fine(" (setParameters)VALUES=" + p.values + "SQLTYPES=" + p.sqlTypes + ""); | |
354 | + | |
355 | + if (sqlInputItems.size() != p.values.size()) { | |
356 | + throw new IllegalArgumentException("入力パラ数が分析結果と不一致:" + "Input=" + p.values.size() + " analized=" | |
357 | + + sqlInputItems); | |
358 | + } | |
359 | + | |
360 | + for (int i = 0; i < p.values.size(); i++) { | |
361 | + Object o = p.values.get(i); | |
362 | + ConstSqlTypes constSqlTypes = p.sqlTypes.get(i); | |
363 | + | |
364 | + if (constSqlTypes == null) { | |
365 | + preparedStatement.setObject(i + 1, o); | |
366 | + } else { | |
367 | + preparedStatement.setObject(i + 1, o, constSqlTypes.getValue()); | |
368 | + Jdbcacsess2.logger.fine(" (setParameters)" + constSqlTypes); | |
369 | + } | |
370 | + } | |
371 | + } | |
372 | + | |
373 | + /** | |
374 | + * 検索結果を取り出す | |
375 | + * | |
376 | + * @throws Throwable | |
377 | + */ | |
378 | + private void readResultSet() throws Throwable { | |
379 | + | |
380 | + ResultSet resultSet = preparedStatement.getResultSet(); | |
381 | + // getMetaData()は、getResultSet()を実行してから行う。 | |
382 | + // sqliteは、"IllegalStateException: SQLite JDBC: inconsistent internal state" | |
383 | + // 例外が発生する。 | |
384 | + List<ColumnAttributeResult> list = ColumnAttributeResult.convColumnAttributeResult(resultSet.getMetaData()); | |
385 | + | |
386 | + Jdbcacsess2.logger.info(" (task)resultSet opened."); | |
387 | + for (SqlExecutedListener l : sqlExecutedListeners.getListeners(SqlExecutedListener.class)) { | |
388 | + l.resultHeader(list); | |
389 | + } | |
390 | + | |
391 | + int columnCnt = list.size(); | |
392 | + | |
393 | + try { | |
394 | + while (resultSet.next()) { | |
395 | + synchronized (this) { | |
396 | + if (Thread.interrupted()) { | |
397 | + Jdbcacsess2.logger.info(" (task)canceled."); | |
398 | + break; | |
399 | + } | |
400 | + ArrayList<Object> results = new ArrayList<Object>(columnCnt); | |
401 | + for (int i = 1; i <= columnCnt; i++) { | |
402 | + results.add(resultSet.getObject(i)); | |
403 | + } | |
404 | + | |
405 | + rowCnt++; | |
406 | + for (SqlExecutedListener l : sqlExecutedListeners.getListeners(SqlExecutedListener.class)) { | |
407 | + l.resultDetail(rowCnt, results); | |
408 | + } | |
409 | + Jdbcacsess2.logger.finest(" (task)results notified."); | |
410 | + | |
411 | + if (rowCnt % resultRowLimitCnt == 0) { | |
412 | + | |
413 | + available = true; | |
414 | + new Thread() { | |
415 | + @Override | |
416 | + public void run() { | |
417 | + for (SqlExecutedListener l : sqlExecutedListeners.getListeners(SqlExecutedListener.class)) { | |
418 | + l.statusContinue(rowCnt); | |
419 | + } | |
420 | + } | |
421 | + }.start(); | |
422 | + Jdbcacsess2.logger.info(" (task)waiting."); | |
423 | + | |
424 | + while (available) { | |
425 | + try { | |
426 | + wait(); | |
427 | + } catch (InterruptedException e) { | |
428 | + Jdbcacsess2.logger.fine(" (task)interrupted."); | |
429 | + // wait() により割り込みフラグがクリアされたので、 | |
430 | + // 自身にもう一度割り込みをかける。ループ脱出をを検知させる為。 | |
431 | + Thread.currentThread().interrupt(); | |
432 | + break; | |
433 | + } | |
434 | + } | |
435 | + Jdbcacsess2.logger.info(" (task)wake up."); | |
436 | + } | |
437 | + } | |
438 | + } | |
439 | + } catch (Throwable t) { | |
440 | + throw t; | |
441 | + } finally { | |
442 | + resultSet.close(); | |
443 | + Jdbcacsess2.logger.info(" (task)resultSet closed."); | |
444 | + } | |
445 | + } | |
446 | + | |
447 | + /** | |
448 | + * 待機中のSQL実行スレッドを再開する | |
449 | + */ | |
450 | + @Override | |
451 | + public void taskWakeUp() { | |
452 | + synchronized (this) { | |
453 | + available = false; | |
454 | + notifyAll(); | |
455 | + } | |
456 | + } | |
457 | + | |
458 | + /** | |
459 | + * 実行中のSQL実行スレッドを中止を要求する | |
460 | + */ | |
461 | + @Override | |
462 | + public void taskCancel() { | |
463 | + thread.interrupt(); | |
464 | + } | |
465 | + | |
466 | + /** | |
467 | + * SQL実行スレッドの終了を待ち合わせる | |
468 | + */ | |
469 | + @Override | |
470 | + public void taskJoin(int timeoutSeconds) { | |
471 | + Jdbcacsess2.logger.info(" (join)joining..."); | |
472 | + try { | |
473 | + Executors.newSingleThreadExecutor().submit(new Callable<Object>() { | |
474 | + @Override | |
475 | + public Object call() throws Exception { | |
476 | + thread.join(); | |
477 | + return null; | |
478 | + } | |
479 | + }).get(timeoutSeconds, TimeUnit.SECONDS); | |
480 | + } catch (InterruptedException e) { | |
481 | + Jdbcacsess2.logger.log(Level.WARNING, "WARNING", e); | |
482 | + } catch (ExecutionException e) { | |
483 | + e.printStackTrace(); | |
484 | + } catch (TimeoutException e) { | |
485 | + ShowDialog.errorMessage(e); | |
486 | + } | |
487 | + Jdbcacsess2.logger.info(" (join)joined."); | |
488 | + } | |
489 | + | |
490 | + /** | |
491 | + * | |
492 | + * @return 処理時間 単位はミリ秒 | |
493 | + */ | |
494 | + @Override | |
495 | + public long getExecutionTime() { | |
496 | + if (timeMillisThreadStart == 0) { | |
497 | + return 0; | |
498 | + } | |
499 | + if (timeMillisThreadEnd == 0) { | |
500 | + return 0; | |
501 | + } | |
502 | + return timeMillisThreadEnd - timeMillisThreadStart; | |
503 | + } | |
504 | + | |
505 | + @Override | |
506 | + public int getCnt() { | |
507 | + return sqlExecuteSentenceList.size(); | |
508 | + | |
509 | + } | |
522 | 510 | }// class SqlTask end |
523 | 511 | |
524 | 512 |
@@ -1,20 +1,21 @@ | ||
1 | 1 | /* |
2 | 2 | * Copyright 2011 Kazuhiro Shimada |
3 | 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. | |
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 | 6 | * You may obtain a copy of the License at |
7 | 7 | * |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | 9 | * |
10 | - * Unless required by applicable law or agreed to in writing, software | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | 16 | package jdbcacsess2.sqlService; |
17 | 17 | |
18 | +import java.util.EventListener; | |
18 | 19 | import java.util.List; |
19 | 20 | |
20 | 21 | import jdbcacsess2.sqlService.parse.SqlExecuteSentencies.SqlExecuteSentence; |
@@ -25,7 +26,7 @@ | ||
25 | 26 | * @author sima |
26 | 27 | * |
27 | 28 | */ |
28 | -public interface SqlExecutedListener { | |
29 | +public interface SqlExecutedListener extends EventListener { | |
29 | 30 | |
30 | 31 | /** |
31 | 32 | * SQL実行が受け付けた時に呼ばれます。このイベントだけは、呼出と同じスレッドで呼ばれ、SQL実行スレッドからではありません。 |