工具类
import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource; import org.apache.log4j.Logger; /** * * @Title: J * @ClassName:JdbcUtil.java * @Description: * * @Copyright 2016-2017 新开普 - Powered By 研发中心 * @author: FLY * @date:2017年9月27日 下午5:01:29 * @version V1.0 */ public class JdbcUtil { // 定义数据库的链接 private static Connection conn; // 定义sql语句的执行对象 private static PreparedStatement pstmt; // 定义查询返回的结果集合 private static ResultSet rs; static Logger jdbcLog = LoggerUtil.getLogger("gateway", "jdbc");// 数据库连接日志 /** * * @Title: 获取数据库连接 * @Description: * * @author: FLY * @date:2017年9月27日 下午5:11:01 */ public static void getConnection() { try { Context ic = new InitialContext(); //此处要添加的是查找数据源的名字 但是要加前缀java:comp/env DataSource source = (DataSource)ic.lookup("java:comp/env/jdbc/数据库名"); conn = source.getConnection(); } catch (NamingException e) { jdbcLog.error("【数据源没找到!】,异常信息:"+e); e.printStackTrace(); } catch (SQLException e) { jdbcLog.error("【获取数连接对象失败!】,异常信息:"+e); e.printStackTrace(); } } public static boolean executeBatch(String sql, Object... objs) { int n = 0; try { getConnection(); jdbcLog.info("【进入批量处理】,sql:" + sql+",参数:"+objs); // 那么对于每一条insert语句,都会产生一条log写入磁盘 conn.setAutoCommit(false); pstmt = conn.prepareStatement(sql); for (int i = 0; i < objs.length; i++) { pstmt.setObject(i + 1, objs[i]); // 1w条记录插入一次 if (i % 10000 == 0){ pstmt.executeBatch(); conn.commit(); } } // 最后插入不足1w条的数据 int[] executeBatch = pstmt.executeBatch(); conn.commit(); //更新条数 n= executeBatch.length; jdbcLog.warn("【批量处理】,更新条数:"+n); } catch (SQLException e) { e.printStackTrace(); jdbcLog.warn("【批量处理异常】,异常信息:"+e); } finally { close(conn, pstmt, rs); } return n > 0 ? true : false; } /** * 执行数据库插入操作 * * @param datas 插入数据表中key为列名和value为列对应的值的Map对象的List集合 * @param tableName 要插入的数据库的表名 * @return 影响的行数 * @throws SQLException SQL异常 */ public static int executeBatchInsert(String tableName, List<Map<String, Object>> datas) throws SQLException { long startTime=System.currentTimeMillis();//记录开始时间 jdbcLog.info("【批量插入】,数据表:" + tableName+" ,要插入的数据:"+datas); /**影响的行数**/ int affectRowCount = -1; try { /**从数据库连接池中获取数据库连接**/ getConnection(); /**设置不自动提交,以便于在出现异常的时候数据库回滚**/ conn.setAutoCommit(false); Map<String, Object> valueMap = datas.get(0); /**获取数据库插入的Map的键值对的值**/ Set<String> keySet = valueMap.keySet(); Iterator<String> iterator = keySet.iterator(); /**要插入的字段sql,其实就是用key拼起来的**/ StringBuilder columnSql = new StringBuilder(); /**要插入的字段值,其实就是?**/ StringBuilder unknownMarkSql = new StringBuilder(); Object[] keys = new Object[valueMap.size()]; // 要执行到数据库的SQL String sqlStr = ""; int i = 0; while (iterator.hasNext()) { String key = iterator.next(); keys[i] = key; columnSql.append(i == 0 ? "" : ","); columnSql.append(key); unknownMarkSql.append(i == 0 ? "" : ","); unknownMarkSql.append("?"); i++; } /**开始拼插入的sql语句**/ StringBuilder sql = new StringBuilder(); sql.append("INSERT INTO "); sql.append(tableName); sql.append(" ("); sql.append(columnSql); sql.append(" ) VALUES "); /*sql.append(" ) VALUES ("); sql.append(unknownMarkSql); sql.append(" )");*/ // jdbcLog.info("【批量插入】,数据表:" + tableName+" ,SQL:"+sql.toString()); // StringBuffer sql = new StringBuffer(); int dataCount = datas.size(); for (int j = 0; j < dataCount; j++) { for (int k = 0; k < keys.length; k++) { // pstmt.setObject(k + 1, datas.get(j).get(keys[k])); /*sql.append(" ("); sql.append(datas.get(j).get(keys[k]));*/ if(k == 0){ sql.append(" ("); sql.append("'").append(datas.get(j).get(keys[k])).append("'"); sql.append(" ,"); }else if(k == keys.length-1){ sql.append("'").append(datas.get(j).get(keys[k])).append("'"); sql.append(" ),"); }else{ sql.append("'").append(datas.get(j).get(keys[k])).append("'"); sql.append(" ,"); } } // 每1000个提交一次 if ((j != 0 && j % 1000 == 0) || j == dataCount - 1) { sqlStr = sql.substring(0, sql.length() - 1); // jdbcLog.info("【批量插入】,数据表:" + tableName+" ,最终SQL:"+sqlStr); /**执行SQL预编译**/ pstmt = conn.prepareStatement(""); pstmt.addBatch(sqlStr); } } int[] arr = pstmt.executeBatch(); conn.commit(); long endTime=System.currentTimeMillis();//记录结束时间 float excTime=(float)(endTime-startTime)/1000; affectRowCount = arr.length; jdbcLog.info("【批量插入】,数据表:" + tableName+" ,最终SQL:"+sql.toString()+" ,返回:["+ affectRowCount + "] 行"+" ,执行时间:["+excTime+"]s"); } catch (Exception e) { e.printStackTrace(); jdbcLog.error("【批量插入异常】,数据表:" + tableName+" ,异常信息:"+e); if (conn != null) { conn.rollback(); } // throw e; } finally { close(conn, pstmt, rs); } return affectRowCount; } /** * 执行数据库插入操作 * * @param datas 插入数据表中key为列名和value为列对应的值的Map对象的List集合 * @param tableName 要插入的数据库的表名 * @return 影响的行数 * @throws SQLException SQL异常 */ public static int batchInsert(String tableName, List<Map<String, Object>> datas) throws SQLException { jdbcLog.info("【批量插入】,数据表:" + tableName+" ,要插入的数据:"+datas); /**影响的行数**/ int affectRowCount = -1; try { /**从数据库连接池中获取数据库连接**/ getConnection(); conn.setAutoCommit(false); Map<String, Object> valueMap = datas.get(0); /**获取数据库插入的Map的键值对的值**/ Set<String> keySet = valueMap.keySet(); Iterator<String> iterator = keySet.iterator(); /**要插入的字段sql,其实就是用key拼起来的**/ StringBuilder columnSql = new StringBuilder(); /**要插入的字段值,其实就是?**/ StringBuilder unknownMarkSql = new StringBuilder(); Object[] keys = new Object[valueMap.size()]; int i = 0; while (iterator.hasNext()) { String key = iterator.next(); keys[i] = key; columnSql.append(i == 0 ? "" : ","); columnSql.append(key); unknownMarkSql.append(i == 0 ? "" : ","); unknownMarkSql.append("?"); i++; } /**开始拼插入的sql语句**/ StringBuilder sql = new StringBuilder(); sql.append("INSERT INTO "); sql.append(tableName); sql.append(" ("); sql.append(columnSql); sql.append(" ) VALUES ("); sql.append(unknownMarkSql); sql.append(" )"); /**执行SQL预编译**/ pstmt = conn.prepareStatement(sql.toString()); /**设置不自动提交,以便于在出现异常的时候数据库回滚**/ // conn.setAutoCommit(false); jdbcLog.info("【批量插入】,数据表:" + tableName+" ,SQL:"+sql.toString()); for (int j = 0; j < datas.size(); j++) { for (int k = 0; k < keys.length; k++) { pstmt.setObject(k + 1, datas.get(j).get(keys[k])); } pstmt.addBatch(); } int[] arr = pstmt.executeBatch(); jdbcLog.info("【批量插入】,数据表:" + tableName+" ,最终SQL:["+ pstmt.toString() + "] "); conn.commit(); affectRowCount = arr.length; jdbcLog.info("【批量插入】,数据表:" + tableName+" ,成功了插入了:["+ affectRowCount + "] 行"); } catch (Exception e) { e.printStackTrace(); jdbcLog.error("【批量插入异常】,数据表:" + tableName+" ,异常信息:"+e); if (conn != null) { conn.rollback(); } // throw e; } finally { close(conn, pstmt, rs); } return affectRowCount; } /** * * @Title: 批量更新 * @param sql * @param objs * @return boolean * @Description: * * @author: FLY * @date:2017年9月27日 下午4:40:38 */ public static boolean executeUpdate(String sql, Object... objs) { int n = 0; try { getConnection(); jdbcLog.info("【进入批量更新】,sql:" + sql+",参数:"+objs); pstmt = conn.prepareStatement(sql); for (int i = 0; i < objs.length; i++) { pstmt.setObject(i + 1, objs[i]); } n = pstmt.executeUpdate(); jdbcLog.warn("【批量更新】,更新条数:"+n); } catch (SQLException e) { e.printStackTrace(); jdbcLog.warn("【批量更新异常】,异常信息:"+e); } finally { close(conn, pstmt, rs); } return n > 0 ? true : false; } /** * * @Title: 查询 * @param sql * @param objs * @return int * @Description: * * @author: FLY * @date:2017年9月27日 下午4:44:57 */ public static int queryForInt(String sql, Object... objs) { try { getConnection(); pstmt = conn.prepareStatement(sql); for (int i = 0; i < objs.length; i++) { pstmt.setObject(i + 1, objs[i]); } rs = pstmt.executeQuery(); if (rs.next()) return rs.getInt(1); } catch (SQLException e) { e.printStackTrace(); } finally { close(conn, pstmt, rs); } return 0; } /** * * @Title: 释放数据库连接 * @param conn * @param stmt * @param rs void * @Description: * * @author: FLY * @date:2017年9月27日 下午4:44:31 */ public static void close(Connection conn, Statement stmt, ResultSet rs) { if (rs != null){ try { rs.close(); } catch (Exception e) { e.printStackTrace(); jdbcLog.error("【释放返回结果集异常】,异常信息:"+e); } } if (stmt != null){ try { stmt.close(); } catch (Exception e) { e.printStackTrace(); jdbcLog.error("【释放sql语句的执行对象异常】,异常信息:"+e); } } if (conn != null){ try { conn.close(); } catch (Exception e) { e.printStackTrace(); jdbcLog.error("【释放数据库连接异常】,异常信息:"+e); } } } }
rewriteBatchedStatements
在数据库连接语句上少了启用rewriteBatchedStatements参数,可以再提高插入速度
如果不开启rewriteBatchedStatements=true,那么jdbc会把批量插入当做一行行的单条处理,也即没有达到批量插入的效果
jdbc:mysql://IP:PORT/database?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&rewriteBatchedStatements=true