package com.haogrgr.test.server; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.List; import javax.annotation.Resource; import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; @Service public class TestMysqlJDBCPrepServiceImpl { @Resource private JdbcTemplate jdbcTemplate; public void test(List<Long> ids) { //默认客户端预编译, 批量更新时, 其实只是将每条sql替换参数, 发送到服务端执行, 和一条条执行基本类似 //com.mysql.cj.jdbc.PreparedStatement.executeInternal(int, Buffer, boolean, boolean, Field[], boolean) //断点上面的方法, rs = locallyScopedConnection.execSQL(..., sendPacket, ...); //这行, 可以看到, sendPacket里面就是替换参数后的sql, 然后外面是一个循环, 一条条执行 //服务端预编译的情况, 参考下面的链接 //http://stackoverflow.com/questions/32286518/whats-the-difference-between-cacheprepstmts-and-useserverprepstmts-in-mysql-jdb/32645365#32645365 //https://dev.mysql.com/doc/internals/en/prepared-statements.html //服务端的情况下, prep的时候, sql就发送给server, 然后server返回一个handle, 参数的发送只会发送参数和这个handle给server //prep可以缓存, 特别是服务端预编译的情况下. jdbcTemplate.batchUpdate("update test set name = ? where id = ?", new BatchPreparedStatementSetter() { @Override public void setValues(PreparedStatement prep, int index) throws SQLException { prep.setString(1, "ddd" + index); prep.setLong(2, ids.get(index)); } @Override public int getBatchSize() { return ids.size(); } }); } }