代码
private void logDataDb(ArrayList<ReceiveData> datas) { Connection conn = null; PreparedStatement pstmt = null; String sql = "INSERT INTO MON_ALARM_LOG (TIME,TOPIC,DIMENSION,CURRENTVALUE,ALERTMAIL,ALERTPHONE,DESCRIPTION,LEVEL) " + " VALUES(?,?,?,?,?,?,?,?)"; try { conn = DBUtils.getConnection(dbcpPath); conn.setAutoCommit(false); pstmt = conn.prepareStatement(sql); pstmt.clearBatch(); Iterator<ReceiveData> ite = datas.iterator(); while (ite.hasNext()) { ReceiveData data = ite.next(); pstmt.setTimestamp(1, data.getTime()); pstmt.setString(2, data.getTopic()); pstmt.setString(3, data.getDimension()); pstmt.setDouble(4, data.getValue()); pstmt.setString(5, data.getAlertMail()); pstmt.setString(6, data.getAlertPhone()); pstmt.setString(7, data.getDescription()); pstmt.setInt(8, data.getLevel()); pstmt.addBatch(); } pstmt.executeBatch(); conn.commit(); conn.setAutoCommit(true); } catch (SQLException e) { LOG.error("保存切片数据出错,MsgAndDbSink.logDataDb()" + e); }finally{ if(pstmt!=null) try { pstmt.close(); } catch (SQLException e) { e.printStackTrace(); } if(conn!=null) try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
1、当一次性需要向数据库插入多条数据时,应该使用jdbc的batch操作。
2、在使用batch插入的时候,需要将connection的autoCommit设置为false,否则将会影响性能,与逐条插入无异。
3、在executeBatch()之后,需要进行connection.commit()因为在之前已将autoCommit设为false,需要手工commit。
4、在最后connection.close()之前,需要将connection的autoCommit设置为其默认的true。
这是因为对于从连接池获取的connection而言,close()只是将其还给连接池从而达到复用的目的,如果不将autoCommit恢复到默认的true,那么之后该connection被其他
程序取出使用的时候,将仍然是一个autoCommit=false的链接。 容易引起问题。 且由于连接池的池资源特性,该问题会成为一个不知何时会发生、难以人工重现的问题。