Java tutorial
/*(C) 2007-2012 Alibaba Group Holding Limited. *This program is free software; you can redistribute it and/or modify *it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * Authors: * junyu <junyu@taobao.com> , shenxun <shenxun@taobao.com>, * linxuan <linxuan@taobao.com> ,qihao <qihao@taobao.com> */ package com.taobao.tddl.jdbc.group; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.Statement; import java.util.LinkedList; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.taobao.tddl.interact.rule.bean.SqlType; import com.taobao.tddl.jdbc.group.dbselector.DBSelector.AbstractDataSourceTryer; import com.taobao.tddl.jdbc.group.dbselector.DBSelector.DataSourceTryer; import com.taobao.tddl.jdbc.group.util.GroupHintParser; import com.taobao.tddl.jdbc.group.util.SQLParser; /** * * @author linxuan * @author yangzhu * */ public class TGroupStatement implements Statement { private static final Log log = LogFactory.getLog(TGroupStatement.class); protected TGroupConnection tGroupConnection; protected TGroupDataSource tGroupDataSource; protected int retryingTimes; public TGroupStatement(TGroupDataSource tGroupDataSource, TGroupConnection tGroupConnection) { this.tGroupDataSource = tGroupDataSource; this.tGroupConnection = tGroupConnection; this.retryingTimes = tGroupDataSource.getRetryingTimes(); } /* ======================================================================== * ()Statementgetter/setter * ======================================================================*/ private Statement baseStatement; /** * Statement * baseStatement * @param baseStatement */ void setBaseStatement(Statement baseStatement) { if (this.baseStatement != null) { try { this.baseStatement.close(); } catch (SQLException e) { log.error("close baseStatement failed.", e); } } this.baseStatement = baseStatement; } /** * query time out . 0setquery */ protected int queryTimeout = 0; protected int fetchSize; protected int maxRows; /** * getResult. * * statement */ protected ResultSet currentResultSet; /** * query-1 */ protected int updateCount; protected int resultSetType = ResultSet.TYPE_FORWARD_ONLY;; protected int resultSetConcurrency = ResultSet.CONCUR_READ_ONLY; //jdbcresultSetHoldabilityResultSet.CLOSE_CURSORS_AT_COMMIT? //TODO -1? protected int resultSetHoldability = -1; public boolean execute(String sql) throws SQLException { return executeInternal(sql, -1, null, null); } public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { return executeInternal(sql, autoGeneratedKeys, null, null); } public boolean execute(String sql, int[] columnIndexes) throws SQLException { return executeInternal(sql, -1, columnIndexes, null); } public boolean execute(String sql, String[] columnNames) throws SQLException { return executeInternal(sql, -1, null, columnNames); } //jdbc: trueexecuteQueryfalseexecuteUpdate private boolean executeInternal(String sql, int autoGeneratedKeys, int[] columnIndexes, String[] columnNames) throws SQLException { SqlType sqlType = SQLParser.getSqlType(sql); if (sqlType == SqlType.SELECT || sqlType == SqlType.SELECT_FOR_UPDATE || sqlType == SqlType.SHOW) { executeQuery(sql); return true; } else if (sqlType == SqlType.INSERT || sqlType == SqlType.UPDATE || sqlType == SqlType.DELETE || sqlType == SqlType.REPLACE || sqlType == SqlType.TRUNCATE || sqlType == SqlType.CREATE || sqlType == SqlType.DROP || sqlType == SqlType.LOAD || sqlType == SqlType.MERGE) { if (autoGeneratedKeys == -1 && columnIndexes == null && columnNames == null) { executeUpdate(sql); } else if (autoGeneratedKeys != -1) { executeUpdate(sql, autoGeneratedKeys); } else if (columnIndexes != null) { executeUpdate(sql, columnIndexes); } else if (columnNames != null) { executeUpdate(sql, columnNames); } else { executeUpdate(sql); } return false; } else { throw new SQLException( "only select, insert, update, delete,replace,truncate,create,drop,load,merge sql is supported"); } } /* ======================================================================== * executeUpdate * ======================================================================*/ public int executeUpdate(String sql) throws SQLException { return executeUpdateInternal(sql, -1, null, null); } public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { return executeUpdateInternal(sql, autoGeneratedKeys, null, null); } public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { return executeUpdateInternal(sql, -1, columnIndexes, null); } public int executeUpdate(String sql, String[] columnNames) throws SQLException { return executeUpdateInternal(sql, -1, null, columnNames); } private int executeUpdateInternal(String sql, int autoGeneratedKeys, int[] columnIndexes, String[] columnNames) throws SQLException { checkClosed(); ensureResultSetIsEmpty(); Connection conn = tGroupConnection.getBaseConnection(sql, false); if (conn != null) { sql = GroupHintParser.removeTddlGroupHint(sql); this.updateCount = executeUpdateOnConnection(conn, sql, autoGeneratedKeys, columnIndexes, columnNames); return this.updateCount; } else { Integer dataSourceIndex = GroupHintParser.convertHint2Index(sql); sql = GroupHintParser.removeTddlGroupHint(sql); if (dataSourceIndex < 0) { dataSourceIndex = ThreadLocalDataSourceIndex.getIndex(); } this.updateCount = this.tGroupDataSource.getDBSelector(false).tryExecute(executeUpdateTryer, retryingTimes, sql, autoGeneratedKeys, columnIndexes, columnNames, dataSourceIndex); return this.updateCount; } } private int executeUpdateOnConnection(Connection conn, String sql, int autoGeneratedKeys, int[] columnIndexes, String[] columnNames) throws SQLException { Statement stmt = createStatementInternal(conn, false); if (autoGeneratedKeys == -1 && columnIndexes == null && columnNames == null) { return stmt.executeUpdate(sql); } else if (autoGeneratedKeys != -1) { return stmt.executeUpdate(sql, autoGeneratedKeys); } else if (columnIndexes != null) { return stmt.executeUpdate(sql, columnIndexes); } else if (columnNames != null) { return stmt.executeUpdate(sql, columnNames); } else { return stmt.executeUpdate(sql); } } private DataSourceTryer<Integer> executeUpdateTryer = new AbstractDataSourceTryer<Integer>() { public Integer tryOnDataSource(DataSourceWrapper dsw, Object... args) throws SQLException { Connection conn = TGroupStatement.this.tGroupConnection.createNewConnection(dsw, false); return executeUpdateOnConnection(conn, (String) args[0], (Integer) args[1], (int[]) args[2], (String[]) args[3]); } }; /** * setBaseStatementStatement */ private Statement createStatementInternal(Connection conn, boolean isBatch) throws SQLException { Statement stmt; if (isBatch) stmt = conn.createStatement(); else { int resultSetHoldability = this.resultSetHoldability; if (resultSetHoldability == -1) //setResultSetHoldability resultSetHoldability = conn.getHoldability(); stmt = conn.createStatement(this.resultSetType, this.resultSetConcurrency, resultSetHoldability); } setBaseStatement(stmt); //Statement stmt.setQueryTimeout(queryTimeout); // stmt.setFetchSize(fetchSize); stmt.setMaxRows(maxRows); return stmt; } /* ======================================================================== * executeBatch * ======================================================================*/ protected List<String> batchedArgs; public void addBatch(String sql) throws SQLException { checkClosed(); if (batchedArgs == null) { batchedArgs = new LinkedList<String>(); } if (sql != null) { batchedArgs.add(sql); } } public void clearBatch() throws SQLException { checkClosed(); if (batchedArgs != null) { batchedArgs.clear(); } } public int[] executeBatch() throws SQLException { try { checkClosed(); ensureResultSetIsEmpty(); if (batchedArgs == null || batchedArgs.isEmpty()) { return new int[0]; } Connection conn = tGroupConnection.getBaseConnection(null, false); if (conn != null) { // , // getConnection return executeBatchOnConnection(conn, this.batchedArgs); } else { return tGroupDataSource.getDBSelector(false).tryExecute(null, executeBatchTryer, retryingTimes); } } finally { if (batchedArgs != null) batchedArgs.clear(); } } private DataSourceTryer<int[]> executeBatchTryer = new AbstractDataSourceTryer<int[]>() { public int[] tryOnDataSource(DataSourceWrapper dsw, Object... args) throws SQLException { Connection conn = TGroupStatement.this.tGroupConnection.createNewConnection(dsw, false); return executeBatchOnConnection(conn, TGroupStatement.this.batchedArgs); } }; private int[] executeBatchOnConnection(Connection conn, List<String> batchedSqls) throws SQLException { Statement stmt = createStatementInternal(conn, true); for (String sql : batchedSqls) { stmt.addBatch(sql); } return stmt.executeBatch(); } /* ======================================================================== * * ======================================================================*/ protected boolean closed; //statment public void close() throws SQLException { close(true); } void close(boolean removeThis) throws SQLException { if (closed) { return; } closed = true; try { if (currentResultSet != null) currentResultSet.close(); } catch (SQLException e) { log.warn("Close currentResultSet failed.", e); } finally { currentResultSet = null; } try { if (this.baseStatement != null) this.baseStatement.close(); } finally { this.baseStatement = null; if (removeThis) tGroupConnection.removeOpenedStatements(this); } } protected void checkClosed() throws SQLException { if (closed) { throw new SQLException("No operations allowed after statement closed."); } } /** * jdbc * * @throws SQLException */ protected void ensureResultSetIsEmpty() throws SQLException { if (currentResultSet != null) { //log.debug("result set is not null,close current result set"); try { currentResultSet.close(); } catch (SQLException e) { log.error("exception on close last result set . can do nothing..", e); } finally { // currentResultSet = null; } } } /* ======================================================================== * executeQuery * ======================================================================*/ public ResultSet executeQuery(String sql) throws SQLException { checkClosed(); ensureResultSetIsEmpty(); boolean gotoRead = SqlType.SELECT.equals(SQLParser.getSqlType(sql)) && tGroupConnection.getAutoCommit(); Connection conn = tGroupConnection.getBaseConnection(sql, gotoRead); if (conn != null) { sql = GroupHintParser.removeTddlGroupHint(sql); return executeQueryOnConnection(conn, sql); } else { // hint Integer dataSourceIndex = GroupHintParser.convertHint2Index(sql); sql = GroupHintParser.removeTddlGroupHint(sql); if (dataSourceIndex < 0) { dataSourceIndex = ThreadLocalDataSourceIndex.getIndex(); } return this.tGroupDataSource.getDBSelector(gotoRead).tryExecute(executeQueryTryer, retryingTimes, sql, dataSourceIndex); } } protected ResultSet executeQueryOnConnection(Connection conn, String sql) throws SQLException { Statement stmt = createStatementInternal(conn, false); this.currentResultSet = stmt.executeQuery(sql); return this.currentResultSet; } protected DataSourceTryer<ResultSet> executeQueryTryer = new AbstractDataSourceTryer<ResultSet>() { public ResultSet tryOnDataSource(DataSourceWrapper dsw, Object... args) throws SQLException { String sql = (String) args[0]; Connection conn = TGroupStatement.this.tGroupConnection.createNewConnection(dsw, true); return executeQueryOnConnection(conn, sql); } }; public SQLWarning getWarnings() throws SQLException { checkClosed(); if (baseStatement != null) return baseStatement.getWarnings(); return null; } public void clearWarnings() throws SQLException { checkClosed(); if (baseStatement != null) baseStatement.clearWarnings(); } /* ======================================================================== * * ======================================================================*/ /** * */ protected boolean moreResults; public boolean getMoreResults() throws SQLException { return moreResults; } public int getQueryTimeout() throws SQLException { return queryTimeout; } public void setQueryTimeout(int queryTimeout) throws SQLException { this.queryTimeout = queryTimeout; } public ResultSet getResultSet() throws SQLException { return currentResultSet; } public int getUpdateCount() throws SQLException { return updateCount; } public int getResultSetConcurrency() throws SQLException { return resultSetConcurrency; } public int getResultSetHoldability() throws SQLException { return resultSetHoldability; } public int getResultSetType() throws SQLException { return resultSetType; } public void setResultSetType(int resultSetType) { this.resultSetType = resultSetType; } public void setResultSetConcurrency(int resultSetConcurrency) { this.resultSetConcurrency = resultSetConcurrency; } public void setResultSetHoldability(int resultSetHoldability) { this.resultSetHoldability = resultSetHoldability; } public Connection getConnection() throws SQLException { return tGroupConnection; } /* ======================================================================== * * ======================================================================*/ public int getFetchDirection() throws SQLException { throw new UnsupportedOperationException("getFetchDirection"); } public int getFetchSize() throws SQLException { return this.fetchSize; } public int getMaxFieldSize() throws SQLException { throw new UnsupportedOperationException("getMaxFieldSize"); } public int getMaxRows() throws SQLException { return this.maxRows; } public void setCursorName(String cursorName) throws SQLException { throw new UnsupportedOperationException("setCursorName"); } public void setEscapeProcessing(boolean escapeProcessing) throws SQLException { throw new UnsupportedOperationException("setEscapeProcessing"); } public boolean getMoreResults(int current) throws SQLException { throw new UnsupportedOperationException("getMoreResults"); } public void setFetchDirection(int fetchDirection) throws SQLException { throw new UnsupportedOperationException("setFetchDirection"); } public void setFetchSize(int fetchSize) throws SQLException { this.fetchSize = fetchSize; } public void setMaxFieldSize(int maxFieldSize) throws SQLException { throw new UnsupportedOperationException("setMaxFieldSize"); } public void setMaxRows(int maxRows) throws SQLException { this.maxRows = maxRows; } public ResultSet getGeneratedKeys() throws SQLException { if (this.baseStatement != null) return this.baseStatement.getGeneratedKeys(); else throw new SQLException("getGeneratedKeys"); //throw new UnsupportedOperationException("getGeneratedKeys"); } public void cancel() throws SQLException { throw new UnsupportedOperationException("cancel"); } public boolean isWrapperFor(Class<?> iface) throws SQLException { return this.getClass().isAssignableFrom(iface); } @SuppressWarnings("unchecked") public <T> T unwrap(Class<T> iface) throws SQLException { try { return (T) this; } catch (Exception e) { throw new SQLException(e); } } public boolean isClosed() throws SQLException { throw new SQLException("not support exception"); } public void setPoolable(boolean poolable) throws SQLException { throw new SQLException("not support exception"); } public boolean isPoolable() throws SQLException { throw new SQLException("not support exception"); } }