1 /* $Id: ClusterStatement.java 94 2008-12-18 11:07:17Z dobashi $
\r
3 * (c)2004 Lavans Networks Inc. All Rights Reserved.
\r
5 package com.lavans.luz2.sql.cluster;
\r
7 import java.lang.reflect.InvocationTargetException;
\r
8 import java.sql.Connection;
\r
9 import java.sql.ResultSet;
\r
10 import java.sql.SQLException;
\r
11 import java.sql.SQLWarning;
\r
12 import java.sql.Statement;
\r
13 import java.util.ArrayList;
\r
14 import java.util.List;
\r
16 import org.apache.commons.logging.Log;
\r
17 import org.apache.commons.logging.LogFactory;
\r
23 public class ClusterStatement implements Statement, ClusterStatementInterface{
\r
24 /** Messageクラスに移動? */
\r
25 protected static final String MSG_ERR_REUPDATE="Statementの再生成に失敗。";
\r
26 protected static final String MSG_WARN_SWITCH_DB="障害が出たので接続先を切り替えます。";
\r
29 private Statement st=null;
\r
31 /** コネクション。障害時に別のStaementを作るよう依頼する。 */
\r
32 private ClusterConnection con = null;
\r
36 * 障害が発生した場合、ClusterPreparedStatementに対する操作を操作が行われた
\r
39 private List<CalledMethod> methodList = null;
\r
41 /** 実行されたsql文。障害時にResultSetを再生成するのに必要。 */
\r
42 private String sql = null;
\r
45 private static Log logger = LogFactory.getLog(ClusterStatement.class);
\r
51 public ClusterStatement(ClusterConnection con, Statement st){
\r
54 methodList = new ArrayList<CalledMethod>();
\r
58 * DB切替時、新たに取得したStatementに対して
\r
62 public void reupdateStatement(Statement st) throws SQLException{
\r
63 try { this.st.close(); } catch (SQLException se) {}
\r
66 for(int i=0; i<methodList.size(); i++){
\r
67 CalledMethod calledMethod = methodList.get(i);
\r
69 calledMethod.invoke(st); // 戻り値は無視して良い
\r
70 }catch (Exception e) {
\r
71 logger.error("reupdate failed",e);
\r
72 throw new SQLException(MSG_ERR_REUPDATE);
\r
78 * クラスタリング対応のメソッド実行処理。
\r
82 * @throws SQLException
\r
84 private Object clusterCall(String methodName, Object[] args, Class<?>[] parameterTypes, boolean saveMethod) throws SQLException{
\r
85 Object result = null;
\r
86 CalledMethod calledMethod = new CalledMethod(methodName, args, parameterTypes);
\r
88 logger.debug(calledMethod.toString());
\r
91 result = calledMethod.invoke(st);
\r
92 }catch (Exception e) {
\r
93 logger.warn(MSG_WARN_SWITCH_DB, e);
\r
94 // try { st.close(); } catch (SQLException se) {}
\r
95 con.notifyError(this); // エラーを通知。ここでstは新しいものになっているはず。
\r
97 // 再度実行。ここでもさらにエラーがでるならSQLExceptionにラップする。
\r
98 result = calledMethod.invoke(st);
\r
99 }catch (InvocationTargetException e2) {
\r
100 // 例外がSQLExceptionならそのままthrow
\r
101 Throwable t = e2.getTargetException();
\r
102 if(t instanceof SQLException){
\r
103 throw (SQLException)t;
\r
105 // それ以外ならwrapしてthrow
\r
106 SQLException sqle = new SQLException();
\r
107 sqle.initCause(e2.getTargetException());
\r
109 }catch (Exception e2) {
\r
110 SQLException sqle = new SQLException();
\r
111 sqle.initCause(e2);
\r
116 methodList.add(calledMethod);
\r
123 * @see java.sql.Statement#executeQuery(java.lang.String)
\r
125 public ResultSet getAnotherResultSet() throws SQLException {
\r
126 logger.debug("Redo st.executeQuery and get ResultSet.\n"+ sql);
\r
128 // resultSet内で障害を検知したので、再度コネクションを張り直す。
\r
129 con.notifyError(this); // エラーを通知。ここでstは新しいものになっているはず。
\r
130 ResultSet rs = st.executeQuery(sql);
\r
136 * @see java.sql.Statement#executeQuery(java.lang.String)
\r
138 public ResultSet executeQuery(String sql) throws SQLException {
\r
139 ResultSet rs = (ResultSet)clusterCall("executeQuery", new Object[]{sql}, new Class[]{String.class}, true);
\r
141 return new ClusterResultSet(this,rs);
\r
145 * @see java.sql.Statement#executeUpdate(java.lang.String)
\r
147 public int executeUpdate(String sql) throws SQLException {
\r
148 return ((Integer)clusterCall("executeUpdate", new Object[]{sql}, new Class[]{String.class}, true)).intValue();
\r
152 * @see java.sql.Statement#executeUpdate(java.lang.String, int)
\r
154 public int executeUpdate(String sql, int autoGeneratedKeys)
\r
155 throws SQLException {
\r
156 return ((Integer)clusterCall("executeUpdate", new Object[]{sql, new Integer(autoGeneratedKeys)},
\r
157 new Class[]{String.class, Integer.TYPE}, true)).intValue();
\r
161 * @see java.sql.Statement#executeUpdate(java.lang.String, int[])
\r
163 public int executeUpdate(String sql, int[] columnIndexes)
\r
164 throws SQLException {
\r
165 return ((Integer)clusterCall("executeUpdate", new Object[]{sql, columnIndexes},
\r
166 new Class[]{String.class, int[].class}, true)).intValue();
\r
170 * @see java.sql.Statement#executeUpdate(java.lang.String, java.lang.String[])
\r
172 public int executeUpdate(String sql, String[] columnNames)
\r
173 throws SQLException {
\r
174 return ((Integer)clusterCall("executeUpdate", new Object[]{sql, columnNames},
\r
175 new Class[]{String.class, String[].class}, true)).intValue();
\r
179 * @see java.sql.Statement#execute(java.lang.String, int)
\r
181 public boolean execute(String sql, int autoGeneratedKeys)
\r
182 throws SQLException {
\r
183 return ((Boolean)clusterCall("execute", new Object[]{sql, new Integer(autoGeneratedKeys)},
\r
184 new Class[]{String.class, Integer.TYPE}, true)).booleanValue();
\r
188 * @see java.sql.Statement#execute(java.lang.String)
\r
190 public boolean execute(String sql) throws SQLException {
\r
191 return ((Boolean)clusterCall("execute", new Object[]{sql},
\r
192 new Class[]{String.class}, true)).booleanValue();
\r
196 * @see java.sql.Statement#execute(java.lang.String, int[])
\r
198 public boolean execute(String sql, int[] columnIndexes)
\r
199 throws SQLException {
\r
200 return ((Boolean)clusterCall("execute", new Object[]{sql, columnIndexes},
\r
201 new Class[]{String.class, int[].class}, true)).booleanValue();
\r
205 * @see java.sql.Statement#execute(java.lang.String, java.lang.String[])
\r
207 public boolean execute(String sql, String[] columnNames)
\r
208 throws SQLException {
\r
209 return ((Boolean)clusterCall("execute", new Object[]{sql, columnNames},
\r
210 new Class[]{String.class, String[].class}, true)).booleanValue();
\r
214 * @see java.sql.Statement#getFetchDirection()
\r
216 public int getFetchDirection() throws SQLException {
\r
217 return ((Integer)clusterCall("getFetchDirection", null, null, false)).intValue();
\r
221 * @see java.sql.Statement#getFetchSize()
\r
223 public int getFetchSize() throws SQLException {
\r
224 return ((Integer)clusterCall("getFetchSize", null, null, false)).intValue();
\r
228 * @see java.sql.Statement#getMaxFieldSize()
\r
230 public int getMaxFieldSize() throws SQLException {
\r
231 return ((Integer)clusterCall("getMaxFieldSize", null, null, false)).intValue();
\r
235 * @see java.sql.Statement#getMaxRows()
\r
237 public int getMaxRows() throws SQLException {
\r
238 return ((Integer)clusterCall("getMaxRows", null, null, false)).intValue();
\r
242 * @see java.sql.Statement#getQueryTimeout()
\r
244 public int getQueryTimeout() throws SQLException {
\r
245 return ((Integer)clusterCall("getQueryTimeout", null, null, false)).intValue();
\r
249 * @see java.sql.Statement#getResultSetConcurrency()
\r
251 public int getResultSetConcurrency() throws SQLException {
\r
252 return ((Integer)clusterCall("getResultSetConcurrency", null, null, false)).intValue();
\r
256 * @see java.sql.Statement#getResultSetHoldability()
\r
258 public int getResultSetHoldability() throws SQLException {
\r
259 return ((Integer)clusterCall("getResultSetConcurrency", null, null, false)).intValue();
\r
263 * @see java.sql.Statement#getResultSetType()
\r
265 public int getResultSetType() throws SQLException {
\r
266 return ((Integer)clusterCall("getResultSetType", null, null, false)).intValue();
\r
270 * @see java.sql.Statement#getUpdateCount()
\r
272 public int getUpdateCount() throws SQLException {
\r
273 return ((Integer)clusterCall("getUpdateCount", null, null, false)).intValue();
\r
278 * @see java.sql.Statement#cancel()
\r
280 public void cancel() throws SQLException {
\r
281 clusterCall("cancel", null, null, true);
\r
285 * @see java.sql.Statement#clearBatch()
\r
287 public void clearBatch() throws SQLException {
\r
288 clusterCall("clearBatch", null, null, true);
\r
293 * @see java.sql.Statement#clearWarnings()
\r
295 public void clearWarnings() throws SQLException {
\r
296 clusterCall("clearWarnings", null, null, true);
\r
297 st.clearWarnings();
\r
301 * @see java.sql.Statement#close()
\r
303 public void close() throws SQLException {
\r
304 clusterCall("close", null, null, true);
\r
310 * @see java.sql.Statement#getMoreResults()
\r
312 public boolean getMoreResults() throws SQLException {
\r
313 return ((Boolean)clusterCall("getMoreResults", null, null, false)).booleanValue();
\r
317 * @see java.sql.Statement#executeBatch()
\r
319 public int[] executeBatch() throws SQLException {
\r
320 return (int[])clusterCall("executeBatch", null, null, true);
\r
324 * @see java.sql.Statement#setFetchDirection(int)
\r
326 public void setFetchDirection(int direction) throws SQLException {
\r
327 clusterCall("setFetchDirection", new Object[]{new Integer(direction)}, new Class[]{Integer.TYPE}, true);
\r
331 * @see java.sql.Statement#setFetchSize(int)
\r
333 public void setFetchSize(int rows) throws SQLException {
\r
334 clusterCall("setFetchSize", new Object[]{new Integer(rows)}, new Class[]{Integer.TYPE}, true);
\r
338 * @see java.sql.Statement#setMaxFieldSize(int)
\r
340 public void setMaxFieldSize(int max) throws SQLException {
\r
341 clusterCall("setMaxFieldSize", new Object[]{new Integer(max)}, new Class[]{Integer.TYPE}, true);
\r
345 * @see java.sql.Statement#setMaxRows(int)
\r
347 public void setMaxRows(int max) throws SQLException {
\r
348 clusterCall("setMaxRows", new Object[]{new Integer(max)}, new Class[]{Integer.TYPE}, true);
\r
352 * @see java.sql.Statement#setQueryTimeout(int)
\r
354 public void setQueryTimeout(int seconds) throws SQLException {
\r
355 clusterCall("setQueryTimeout", new Object[]{new Integer(seconds)}, new Class[]{Integer.TYPE}, true);
\r
359 * @see java.sql.Statement#getMoreResults(int)
\r
361 public boolean getMoreResults(int current) throws SQLException {
\r
362 return ((Boolean)clusterCall("getMoreResults", new Object[]{new Integer(current)}, new Class[]{Integer.TYPE}, false)).booleanValue();
\r
366 * @see java.sql.Statement#setEscapeProcessing(boolean)
\r
368 public void setEscapeProcessing(boolean enable) throws SQLException {
\r
369 clusterCall("setFetchDirection", new Object[]{new Boolean(enable)}, new Class[]{Boolean.TYPE}, true);
\r
374 * @see java.sql.Statement#addBatch(java.lang.String)
\r
376 public void addBatch(String sql) throws SQLException {
\r
377 clusterCall("addBatch", new Object[]{sql}, new Class[]{String.class}, true);
\r
381 * @see java.sql.Statement#setCursorName(java.lang.String)
\r
383 public void setCursorName(String name) throws SQLException {
\r
384 clusterCall("setCursorName", new Object[]{name}, new Class[]{String.class}, true);
\r
389 * @see java.sql.Statement#getConnection()
\r
391 public Connection getConnection() throws SQLException {
\r
393 // return (Connection)clusterCall("getConnection", null, false);
\r
397 * @see java.sql.Statement#getGeneratedKeys()
\r
399 public ResultSet getGeneratedKeys() throws SQLException {
\r
400 return (ResultSet)clusterCall("getGeneratedKeys", null, null, false);
\r
404 * @see java.sql.Statement#getResultSet()
\r
406 public ResultSet getResultSet() throws SQLException {
\r
407 return (ResultSet)clusterCall("getResultSet", null, null, false);
\r
411 * @see java.sql.Statement#getWarnings()
\r
413 public SQLWarning getWarnings() throws SQLException {
\r
414 return (SQLWarning)clusterCall("getWarnings", null, null, false);
\r
418 * @throws SQLException
\r
419 * @see java.sql.Statement#isClosed()
\r
421 public boolean isClosed() throws SQLException {
\r
422 return st.isClosed();
\r
427 * @throws SQLException
\r
428 * @see java.sql.Statement#isPoolable()
\r
430 public boolean isPoolable() throws SQLException {
\r
431 return st.isPoolable();
\r
437 * @throws SQLException
\r
438 * @see java.sql.Wrapper#isWrapperFor(java.lang.Class)
\r
440 public boolean isWrapperFor(Class<?> iface) throws SQLException {
\r
441 return st.isWrapperFor(iface);
\r
446 * @throws SQLException
\r
447 * @see java.sql.Statement#setPoolable(boolean)
\r
449 public void setPoolable(boolean poolable) throws SQLException {
\r
450 st.setPoolable(poolable);
\r
457 * @throws SQLException
\r
458 * @see java.sql.Wrapper#unwrap(java.lang.Class)
\r
460 @SuppressWarnings("unchecked")
\r
461 public <T> T unwrap(Class<T> iface) throws SQLException {
\r