package com.pictc.jdbc; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.List; import javax.sql.DataSource; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceUtils; import org.springframework.jdbc.support.JdbcUtils; import com.pictc.jdbc.model.JdbcParam; import com.pictc.utils.CollectionUtils; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; @Slf4j @Getter @Setter public class JdbcContext { public static final int DEF_STEP = 1000; private JdbcTemplate jdbc; private DataSource source; private DataSource logSource; private Connection conn; private PreparedStatement stmt; private CallableStatement ctmt; private long start; private int size = 0; private boolean isQuery = false; private boolean isCall = false; private boolean datalog = false; private String sql; private List params; private List> batchParams; public JdbcContext(boolean isQuery) throws SQLException { this(isQuery, false); } public JdbcContext(boolean isQuery,boolean datalog) throws SQLException { super(); this.isQuery = isQuery; this.datalog = datalog; this.start = System.currentTimeMillis(); this.source = JdbcContextUtils.getSource(); this.logSource = JdbcContextUtils.getLogSource(); this.jdbc = JdbcContextUtils.getJdbc(); this.conn = datalog?DataSourceUtils.getConnection(this.logSource):DataSourceUtils.getConnection(this.source); } public JdbcContext init(String sql) throws SQLException { this.sql = sql; this.stmt = (PreparedStatement) getStatement(this.conn,sql); return this; } public DataSource getReleaseSource() { return datalog?logSource:source; } public JdbcContext initCall(String sql) throws SQLException { this.sql = sql; this.isCall = true; this.ctmt = (CallableStatement) getStatement(this.conn,sql); return this; } public JdbcContext addParam(int jdbc,Object val) { if(params==null) { params = CollectionUtils.newArrayList(); } params.add(new JdbcParam().setJdbc(jdbc).setVal(val)); return this; } public JdbcContext addBatchParam(int index,int jdbc,Object val) { if(batchParams==null) { batchParams = CollectionUtils.newArrayList(); } if(batchParams.size() <=index) { batchParams.add(CollectionUtils.newArrayList()); } List bpam = batchParams.get(index); bpam.add(new JdbcParam().setJdbc(jdbc).setVal(val)); return this; } private Statement getStatement(Connection conn,String sql) throws SQLException { Statement stmt = null; if(this.isCall) { stmt = conn.prepareCall(sql); }else if(this.isQuery) { stmt = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); }else { stmt = conn.prepareStatement(sql); } int fetchSize = jdbc.getFetchSize(); if (fetchSize >= 0) { stmt.setFetchSize(fetchSize); } int maxRows = jdbc.getMaxRows(); if (maxRows >= 0) { stmt.setMaxRows(maxRows); } DataSourceUtils.applyTimeout(stmt,getReleaseSource(),jdbc.getQueryTimeout()); return stmt; } private void executeParams() throws SQLException { if(params!=null) { for (int i = 0; i < params.size(); i++) { JdbcParam parameter = params.get(i); int index = i+1; if(parameter.isOut()) { ctmt.registerOutParameter(index,parameter.getJdbc()); continue; } this.setParameter(index,parameter.getJdbc(),parameter.getVal()); } } } public int executeUpdate() throws SQLException { executeParams(); size = this._executeUpdate(); return size; } public boolean execute() throws SQLException { executeParams(); return this._execute(); } public int executeBatch() throws SQLException { return executeBatch(DEF_STEP); } public int executeBatch(int step) throws SQLException { int rows = 0; step = step <=0?DEF_STEP:step; if(batchParams!=null && !batchParams.isEmpty()) { int j = 0; for (List list : batchParams) { for (int i = 0; i < list.size(); i++) { JdbcParam parameter = list.get(i); setParameter(i+1, parameter.getJdbc(),parameter.getVal()); } this.addBatch(); j++; if(j%step==0) { rows=countRow(rows,this._executeBatch()); } } } rows=countRow(rows,this._executeBatch()); size = rows; return rows; } public ResultSet executeQuery() throws SQLException { executeParams(); ResultSet rset = this._executeQuery(); rset.last(); size = rset.getRow(); //获得ResultSet的总行数 rset.beforeFirst(); return rset; } private ResultSet _executeQuery() throws SQLException { return getStatement().executeQuery(); } private PreparedStatement getStatement() { return this.isCall?ctmt:stmt; } private void setParameter(int index,int jdbc,Object val) throws SQLException { PreparedStatement _stmt = getStatement(); if(val==null) { _stmt.setNull(index,jdbc); }else { _stmt.setObject(index,val,jdbc); } } private void addBatch() throws SQLException { getStatement().addBatch(); } private int[] _executeBatch() throws SQLException { return getStatement().executeBatch(); } private int _executeUpdate() throws SQLException { return getStatement().executeUpdate(); } private boolean _execute() throws SQLException { return getStatement().execute(); } private int countRow(int rows,int[] rowArray) { if(rowArray!=null) { for (int i = 0; i < rowArray.length; i++) { rows+=rowArray[i]; } } return rows; } public DataAccessException createException(SQLException e) { return jdbc.getExceptionTranslator().translate(sql,null,e); } public void end() { JdbcUtils.closeStatement(getStatement()); if(conn!=null) { DataSourceUtils.releaseConnection(conn,getReleaseSource()); } log.info(" Statement: 【{}】",sql); if(params!=null && !params.isEmpty()) { log.info("Parameters: {}",params.toString()); } long con = System.currentTimeMillis()-start; if(!this.isQuery) { log.info(" consuming: 【{} ms】--- 数据:【{}条】--- 效率:【{} ms/条】",con,size,size>0?(con/size):con); }else { log.info(" total: {}",size); log.info(" consuming: 【{} ms】",con); } log.info("-----------------------------------------------------------------------------------"); } }