1 /* $Id: ClusterPreparedStatement.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.io.InputStream;
\r
8 import java.io.Reader;
\r
9 import java.math.BigDecimal;
\r
10 import java.net.URL;
\r
11 import java.sql.Array;
\r
12 import java.sql.Blob;
\r
13 import java.sql.Clob;
\r
14 import java.sql.Date;
\r
15 import java.sql.NClob;
\r
16 import java.sql.ParameterMetaData;
\r
17 import java.sql.PreparedStatement;
\r
18 import java.sql.Ref;
\r
19 import java.sql.ResultSet;
\r
20 import java.sql.ResultSetMetaData;
\r
21 import java.sql.RowId;
\r
22 import java.sql.SQLException;
\r
23 import java.sql.SQLXML;
\r
24 import java.sql.Statement;
\r
25 import java.sql.Time;
\r
26 import java.sql.Timestamp;
\r
27 import java.util.ArrayList;
\r
28 import java.util.Calendar;
\r
29 import java.util.List;
\r
31 import org.apache.commons.logging.Log;
\r
32 import org.apache.commons.logging.LogFactory;
\r
35 * PrepareStatementをクラスタ対応化するクラス。
\r
36 * setXX()でセットされたパラメータを保持し、DB切り替えで再実行する際には
\r
39 * executeUpdate()等の更新処理が複数回実行された後、
\r
40 * Commitする前にDB切替が起きた場合、すべての更新処理が再実行される。
\r
41 * 従って、トランザクション内で一つのStatementを持ち回って更新処理を
\r
44 * sequenceを使って連番管理している場合は2カウントアップされる?(要確認)。
\r
49 public class ClusterPreparedStatement
\r
50 extends ClusterStatement
\r
51 implements PreparedStatement {
\r
54 private PreparedStatement st=null;
\r
56 /** コネクション。障害時に別のStaementを作るよう依頼する。 */
\r
57 private ClusterConnection con = null;
\r
61 * 障害が発生した場合、ClusterPreparedStatementに対する操作を操作が行われた
\r
64 private List<CalledMethod> methodList = null;
\r
67 private static Log logger = LogFactory.getLog(ClusterPreparedStatement.class);
\r
73 public ClusterPreparedStatement(ClusterConnection con, PreparedStatement st) {
\r
77 methodList = new ArrayList<CalledMethod>();
\r
81 * @see java.sql.Statement#close()
\r
84 public void close() throws SQLException {
\r
91 * DB切替時、新たに取得したStatementに対して
\r
96 public void reupdateStatement(Statement st) throws SQLException{
\r
97 try { this.st.close(); } catch (SQLException se) {}
\r
98 this.st = (PreparedStatement)st;
\r
100 super.reupdateStatement(st); // ベースクラスでも再実行
\r
101 logger.debug( "reexecute count:"+ methodList.size());
\r
102 for(int i=0; i<methodList.size(); i++){
\r
103 CalledMethod calledMethod = methodList.get(i);
\r
105 logger.debug(calledMethod.toString());
\r
106 calledMethod.invoke(st); // 戻り値は無視して良い
\r
107 }catch (Exception e) {
\r
108 logger.error(MSG_ERR_REUPDATE, e);
\r
109 throw new SQLException(MSG_ERR_REUPDATE);
\r
115 * クラスタリング対応のメソッド実行処理。
\r
116 * @param methodName
\r
119 * @throws SQLException
\r
121 private Object clusterCall(String methodName, Object[] args, Class<?>[] parameterTypes) throws SQLException{
\r
122 Object result = null;
\r
124 CalledMethod calledMethod = new CalledMethod(methodName, args, parameterTypes);
\r
125 logger.debug(calledMethod.toString());
\r
128 result = calledMethod.invoke(st);
\r
129 }catch (Exception e) {
\r
130 logger.warn(MSG_WARN_SWITCH_DB, e);
\r
131 con.notifyError(this);
\r
133 result = calledMethod.invoke(st);
\r
134 }catch (Exception e2) {
\r
135 // 再度実行。ここでもさらにエラーがでるならSQLExceptionにラップする。
\r
136 throw new SQLException(e2.getMessage());
\r
139 methodList.add(calledMethod);
\r
146 * ResultSetで障害が起きたときに、ResultSetから呼ばれる。
\r
147 * @see com.lavans.util.jdbc.cluster.ClusterStatementInterface#getAnotherResultSet()
\r
150 public ResultSet getAnotherResultSet() throws SQLException {
\r
151 // resultSet内で障害を検知したので、再度コネクションを張り直す。
\r
152 try { st.close(); } catch (SQLException se) {}
\r
153 con.notifyError(this);
\r
154 ResultSet rs = st.executeQuery(); // ResultSetを生成するのはexecuteQuery()だけ。
\r
160 * @see java.sql.PreparedStatement#executeQuery()
\r
162 public ResultSet executeQuery() throws SQLException {
\r
163 ResultSet result = (ResultSet)clusterCall("executeQuery", null, null);
\r
164 // executeQueryでもinsert文は実行できるので保存する必要があることに注意。
\r
166 return new ClusterResultSet(this,result);
\r
171 * @see java.sql.PreparedStatement#executeUpdate()
\r
173 public int executeUpdate() throws SQLException {
\r
174 return ((Integer)clusterCall("executeUpdate", null, null)).intValue();
\r
178 * @see java.sql.PreparedStatement#execute()
\r
180 public boolean execute() throws SQLException {
\r
181 return ((Boolean)clusterCall("execute", null, null)).booleanValue();
\r
185 * @see java.sql.PreparedStatement#addBatch()
\r
187 public void addBatch() throws SQLException {
\r
188 clusterCall("addBatch", null, null);
\r
192 * @see java.sql.PreparedStatement#clearParameters()
\r
194 public void clearParameters() throws SQLException {
\r
195 clusterCall("clearParameters", null, null);
\r
196 // methodListをクリアしてもいいのでは?
\r
200 * @see java.sql.PreparedStatement#setByte(int, byte)
\r
202 public void setByte(int parameterIndex, byte x) throws SQLException {
\r
205 new Object[]{new Integer(parameterIndex), new Byte(x)},
\r
206 new Class[]{Integer.TYPE, Byte.TYPE}
\r
211 * @see java.sql.PreparedStatement#setDouble(int, double)
\r
213 public void setDouble(int parameterIndex, double x) throws SQLException {
\r
216 new Object[]{new Integer(parameterIndex), new Double(x)},
\r
217 new Class[]{Integer.TYPE, Double.TYPE}
\r
222 * @see java.sql.PreparedStatement#setFloat(int, float)
\r
224 public void setFloat(int parameterIndex, float x) throws SQLException {
\r
227 new Object[]{new Integer(parameterIndex), new Float(x)},
\r
228 new Class[]{Integer.TYPE, Float.TYPE}
\r
233 * @see java.sql.PreparedStatement#setInt(int, int)
\r
235 public void setInt(int parameterIndex, int x) throws SQLException {
\r
238 new Object[]{new Integer(parameterIndex), new Integer(x)},
\r
239 new Class[]{Integer.TYPE, Integer.TYPE}
\r
244 * @see java.sql.PreparedStatement#setNull(int, int)
\r
246 public void setNull(int parameterIndex, int sqlType) throws SQLException {
\r
249 new Object[]{new Integer(parameterIndex), new Integer(sqlType)},
\r
250 new Class[]{Integer.TYPE, Integer.TYPE}
\r
255 * @see java.sql.PreparedStatement#setLong(int, long)
\r
257 public void setLong(int parameterIndex, long x) throws SQLException {
\r
260 new Object[]{new Integer(parameterIndex), new Long(x)},
\r
261 new Class[]{Integer.TYPE, Long.TYPE}
\r
266 * @see java.sql.PreparedStatement#setShort(int, short)
\r
268 public void setShort(int parameterIndex, short x) throws SQLException {
\r
270 "setShort", new Object[]{new Integer(parameterIndex), new Short(x)},
\r
271 new Class[]{Integer.TYPE, Short.TYPE});
\r
275 * @see java.sql.PreparedStatement#setBoolean(int, boolean)
\r
277 public void setBoolean(int parameterIndex, boolean x) throws SQLException {
\r
278 clusterCall("setBoolean", new Object[]{new Integer(parameterIndex), new Boolean(x)},
\r
279 new Class[]{Integer.TYPE, Boolean.TYPE});
\r
283 * @see java.sql.PreparedStatement#setBytes(int, byte[])
\r
285 public void setBytes(int parameterIndex, byte[] x) throws SQLException {
\r
286 clusterCall("setBytes", new Object[]{new Integer(parameterIndex), x},
\r
287 new Class[]{Integer.TYPE, byte[].class});
\r
293 * @see java.sql.PreparedStatement#setAsciiStream(int, java.io.InputStream, int)
\r
295 public void setAsciiStream(int parameterIndex, InputStream x, int length)
\r
296 throws SQLException {
\r
297 clusterCall("setAsciiStream", new Object[]{new Integer(parameterIndex), x, new Integer(length)},
\r
298 new Class[]{Integer.TYPE, InputStream.class, Integer.TYPE});
\r
302 * @see java.sql.PreparedStatement#setBinaryStream(int, java.io.InputStream, int)
\r
304 public void setBinaryStream(int parameterIndex, InputStream x, int length)
\r
305 throws SQLException {
\r
306 clusterCall("setBinaryStream", new Object[]{new Integer(parameterIndex), x, new Integer(length)},
\r
307 new Class[]{Integer.TYPE, InputStream.class, Integer.TYPE});
\r
311 * @see java.sql.PreparedStatement#setUnicodeStream(int, java.io.InputStream, int)
\r
314 public void setUnicodeStream(int parameterIndex, InputStream x, int length)
\r
315 throws SQLException {
\r
316 clusterCall("setUnicodeStream", new Object[]{new Integer(parameterIndex), x, new Integer(length)},
\r
317 new Class[]{Integer.TYPE, InputStream.class, Integer.TYPE});
\r
321 * @see java.sql.PreparedStatement#setCharacterStream(int, java.io.Reader, int)
\r
323 public void setCharacterStream(
\r
324 int parameterIndex,
\r
327 throws SQLException {
\r
328 clusterCall("setCharacterStream", new Object[]{new Integer(parameterIndex), reader, new Integer(length)},
\r
329 new Class[]{Integer.TYPE, Reader.class, Integer.TYPE});
\r
332 * @see java.sql.PreparedStatement#setObject(int, java.lang.Object)
\r
334 public void setObject(int parameterIndex, Object x) throws SQLException {
\r
337 new Object[]{new Integer(parameterIndex), x},
\r
338 new Class[]{Integer.TYPE, Object.class}
\r
343 * @see java.sql.PreparedStatement#setObject(int, java.lang.Object, int)
\r
345 public void setObject(int parameterIndex, Object x, int targetSqlType)
\r
346 throws SQLException {
\r
349 new Object[]{new Integer(parameterIndex), x, new Integer(targetSqlType)},
\r
350 new Class[]{Integer.TYPE, Object.class, Integer.TYPE}
\r
355 * @see java.sql.PreparedStatement#setObject(int, java.lang.Object, int, int)
\r
357 public void setObject(
\r
358 int parameterIndex,
\r
362 throws SQLException {
\r
365 new Object[]{new Integer(parameterIndex), x, new Integer(targetSqlType), new Integer(scale)},
\r
366 new Class[]{Integer.TYPE, Object.class, Integer.TYPE, Integer.TYPE}
\r
371 * @see java.sql.PreparedStatement#setNull(int, int, java.lang.String)
\r
373 public void setNull(int paramIndex, int sqlType, String typeName)
\r
374 throws SQLException {
\r
375 clusterCall("setNull", new Object[]{new Integer(paramIndex), new Integer(sqlType), typeName},
\r
376 new Class[]{Integer.TYPE, Integer.TYPE, String.class});
\r
380 * @see java.sql.PreparedStatement#setString(int, java.lang.String)
\r
382 public void setString(int parameterIndex, String x) throws SQLException {
\r
385 new Object[]{new Integer(parameterIndex), x},
\r
386 new Class[]{Integer.TYPE, String.class}
\r
391 * @see java.sql.PreparedStatement#setBigDecimal(int, java.math.BigDecimal)
\r
393 public void setBigDecimal(int parameterIndex, BigDecimal x)
\r
394 throws SQLException {
\r
395 clusterCall("setBigDecimal", new Object[]{new Integer(parameterIndex), x},
\r
396 new Class[]{Integer.TYPE, BigDecimal.class});
\r
401 * @see java.sql.PreparedStatement#setURL(int, java.net.URL)
\r
403 public void setURL(int parameterIndex, URL x) throws SQLException {
\r
404 clusterCall("setURL", new Object[]{new Integer(parameterIndex), x},
\r
405 new Class[]{Integer.TYPE, URL.class});
\r
409 * @see java.sql.PreparedStatement#setArray(int, java.sql.Array)
\r
411 public void setArray(int i, Array x) throws SQLException {
\r
412 clusterCall("setArray", new Object[]{new Integer(i), x},
\r
413 new Class[]{Integer.TYPE, Array.class});
\r
417 * @see java.sql.PreparedStatement#setBlob(int, java.sql.Blob)
\r
419 public void setBlob(int i, Blob x) throws SQLException {
\r
420 clusterCall("setBlob", new Object[]{new Integer(i), x},
\r
421 new Class[]{Integer.TYPE, Blob.class});
\r
425 * @see java.sql.PreparedStatement#setClob(int, java.sql.Clob)
\r
427 public void setClob(int i, Clob x) throws SQLException {
\r
428 clusterCall("setClob", new Object[]{new Integer(i), x},
\r
429 new Class[]{Integer.TYPE, Clob.class});
\r
433 * @see java.sql.PreparedStatement#setDate(int, java.sql.Date)
\r
435 public void setDate(int parameterIndex, Date x) throws SQLException {
\r
436 clusterCall("setDate", new Object[]{new Integer(parameterIndex), x},
\r
437 new Class[]{Integer.TYPE, Date.class});
\r
442 * @see java.sql.PreparedStatement#getParameterMetaData()
\r
444 public ParameterMetaData getParameterMetaData() throws SQLException {
\r
445 return (ParameterMetaData)clusterCall("getParameterMetaData", null, null);
\r
449 * @see java.sql.PreparedStatement#setRef(int, java.sql.Ref)
\r
451 public void setRef(int i, Ref x) throws SQLException {
\r
452 clusterCall("setRef", new Object[]{new Integer(i), x},
\r
453 new Class[]{Integer.TYPE, Ref.class});
\r
458 * @see java.sql.PreparedStatement#getMetaData()
\r
460 public ResultSetMetaData getMetaData() throws SQLException {
\r
461 return (ResultSetMetaData)clusterCall("getMetaData", null, null);
\r
465 * @see java.sql.PreparedStatement#setTime(int, java.sql.Time)
\r
467 public void setTime(int parameterIndex, Time x) throws SQLException {
\r
468 clusterCall("setTime", new Object[]{new Integer(parameterIndex), x},
\r
469 new Class[]{Integer.TYPE, Time.class});
\r
473 * @see java.sql.PreparedStatement#setTimestamp(int, java.sql.Timestamp)
\r
475 public void setTimestamp(int parameterIndex, Timestamp x)
\r
476 throws SQLException {
\r
477 clusterCall("setTimestamp", new Object[]{new Integer(parameterIndex), x},
\r
478 new Class[]{Integer.TYPE, Timestamp.class});
\r
482 * @see java.sql.PreparedStatement#setDate(int, java.sql.Date, java.util.Calendar)
\r
484 public void setDate(int parameterIndex, Date x, Calendar cal)
\r
485 throws SQLException {
\r
486 clusterCall("setDate", new Object[]{new Integer(parameterIndex), x, cal},
\r
487 new Class[]{Integer.TYPE, Date.class, Calendar.class});
\r
491 * @see java.sql.PreparedStatement#setTime(int, java.sql.Time, java.util.Calendar)
\r
493 public void setTime(int parameterIndex, Time x, Calendar cal)
\r
494 throws SQLException {
\r
495 clusterCall("setTime", new Object[]{new Integer(parameterIndex), x, cal},
\r
496 new Class[]{Integer.TYPE, Time.class, Calendar.class});
\r
500 * @see java.sql.PreparedStatement#setTimestamp(int, java.sql.Timestamp, java.util.Calendar)
\r
502 public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal)
\r
503 throws SQLException {
\r
504 clusterCall("setTimestamp", new Object[]{new Integer(parameterIndex), x, cal},
\r
505 new Class[]{Integer.TYPE, Timestamp.class, Calendar.class});
\r
512 * @param parameterIndex
\r
515 * @throws SQLException
\r
516 * @see java.sql.PreparedStatement#setAsciiStream(int, java.io.InputStream, long)
\r
518 public void setAsciiStream(int parameterIndex, InputStream x, long length)
\r
519 throws SQLException {
\r
520 st.setAsciiStream(parameterIndex, x, length);
\r
524 * @param parameterIndex
\r
526 * @throws SQLException
\r
527 * @see java.sql.PreparedStatement#setAsciiStream(int, java.io.InputStream)
\r
529 public void setAsciiStream(int parameterIndex, InputStream x)
\r
530 throws SQLException {
\r
531 st.setAsciiStream(parameterIndex, x);
\r
535 * @param parameterIndex
\r
538 * @throws SQLException
\r
539 * @see java.sql.PreparedStatement#setBinaryStream(int, java.io.InputStream, long)
\r
541 public void setBinaryStream(int parameterIndex, InputStream x, long length)
\r
542 throws SQLException {
\r
543 st.setBinaryStream(parameterIndex, x, length);
\r
547 * @param parameterIndex
\r
549 * @throws SQLException
\r
550 * @see java.sql.PreparedStatement#setBinaryStream(int, java.io.InputStream)
\r
552 public void setBinaryStream(int parameterIndex, InputStream x)
\r
553 throws SQLException {
\r
554 st.setBinaryStream(parameterIndex, x);
\r
558 * @param parameterIndex
\r
559 * @param inputStream
\r
561 * @throws SQLException
\r
562 * @see java.sql.PreparedStatement#setBlob(int, java.io.InputStream, long)
\r
564 public void setBlob(int parameterIndex, InputStream inputStream, long length)
\r
565 throws SQLException {
\r
566 st.setBlob(parameterIndex, inputStream, length);
\r
570 * @param parameterIndex
\r
571 * @param inputStream
\r
572 * @throws SQLException
\r
573 * @see java.sql.PreparedStatement#setBlob(int, java.io.InputStream)
\r
575 public void setBlob(int parameterIndex, InputStream inputStream)
\r
576 throws SQLException {
\r
577 st.setBlob(parameterIndex, inputStream);
\r
581 * @param parameterIndex
\r
584 * @throws SQLException
\r
585 * @see java.sql.PreparedStatement#setCharacterStream(int, java.io.Reader, long)
\r
587 public void setCharacterStream(int parameterIndex, Reader reader,
\r
588 long length) throws SQLException {
\r
589 st.setCharacterStream(parameterIndex, reader, length);
\r
593 * @param parameterIndex
\r
595 * @throws SQLException
\r
596 * @see java.sql.PreparedStatement#setCharacterStream(int, java.io.Reader)
\r
598 public void setCharacterStream(int parameterIndex, Reader reader)
\r
599 throws SQLException {
\r
600 st.setCharacterStream(parameterIndex, reader);
\r
604 * @param parameterIndex
\r
607 * @throws SQLException
\r
608 * @see java.sql.PreparedStatement#setClob(int, java.io.Reader, long)
\r
610 public void setClob(int parameterIndex, Reader reader, long length)
\r
611 throws SQLException {
\r
612 st.setClob(parameterIndex, reader, length);
\r
616 * @param parameterIndex
\r
618 * @throws SQLException
\r
619 * @see java.sql.PreparedStatement#setClob(int, java.io.Reader)
\r
621 public void setClob(int parameterIndex, Reader reader) throws SQLException {
\r
622 st.setClob(parameterIndex, reader);
\r
626 * @param parameterIndex
\r
629 * @throws SQLException
\r
630 * @see java.sql.PreparedStatement#setNCharacterStream(int, java.io.Reader, long)
\r
632 public void setNCharacterStream(int parameterIndex, Reader value,
\r
633 long length) throws SQLException {
\r
634 st.setNCharacterStream(parameterIndex, value, length);
\r
638 * @param parameterIndex
\r
640 * @throws SQLException
\r
641 * @see java.sql.PreparedStatement#setNCharacterStream(int, java.io.Reader)
\r
643 public void setNCharacterStream(int parameterIndex, Reader value)
\r
644 throws SQLException {
\r
645 st.setNCharacterStream(parameterIndex, value);
\r
649 * @param parameterIndex
\r
651 * @throws SQLException
\r
652 * @see java.sql.PreparedStatement#setNClob(int, java.sql.NClob)
\r
654 public void setNClob(int parameterIndex, NClob value) throws SQLException {
\r
655 st.setNClob(parameterIndex, value);
\r
659 * @param parameterIndex
\r
662 * @throws SQLException
\r
663 * @see java.sql.PreparedStatement#setNClob(int, java.io.Reader, long)
\r
665 public void setNClob(int parameterIndex, Reader reader, long length)
\r
666 throws SQLException {
\r
667 st.setNClob(parameterIndex, reader, length);
\r
671 * @param parameterIndex
\r
673 * @throws SQLException
\r
674 * @see java.sql.PreparedStatement#setNClob(int, java.io.Reader)
\r
676 public void setNClob(int parameterIndex, Reader reader) throws SQLException {
\r
677 st.setNClob(parameterIndex, reader);
\r
681 * @param parameterIndex
\r
683 * @throws SQLException
\r
684 * @see java.sql.PreparedStatement#setNString(int, java.lang.String)
\r
686 public void setNString(int parameterIndex, String value)
\r
687 throws SQLException {
\r
688 st.setNString(parameterIndex, value);
\r
692 * @param parameterIndex
\r
694 * @throws SQLException
\r
695 * @see java.sql.PreparedStatement#setRowId(int, java.sql.RowId)
\r
697 public void setRowId(int parameterIndex, RowId x) throws SQLException {
\r
698 st.setRowId(parameterIndex, x);
\r
702 * @param parameterIndex
\r
704 * @throws SQLException
\r
705 * @see java.sql.PreparedStatement#setSQLXML(int, java.sql.SQLXML)
\r
707 public void setSQLXML(int parameterIndex, SQLXML xmlObject)
\r
708 throws SQLException {
\r
709 st.setSQLXML(parameterIndex, xmlObject);
\r
715 * @throws SQLException
\r
716 * @see java.sql.Wrapper#isWrapperFor(java.lang.Class)
\r
719 public boolean isWrapperFor(Class<?> iface) throws SQLException {
\r
720 return st.isWrapperFor(iface);
\r
727 * @throws SQLException
\r
728 * @see java.sql.Wrapper#unwrap(java.lang.Class)
\r
731 @SuppressWarnings("unchecked")
\r
732 public <T> T unwrap(Class<T> iface) throws SQLException {
\r