有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java JDBC插入多行

我现在使用的是批处理:

String query = "INSERT INTO table (id, name, value) VALUES (?, ?, ?)";
PreparedStatement ps = connection.prepareStatement(query);            
for (Record record : records) {
    ps.setInt(1, record.id);
    ps.setString(2, record.name);
    ps.setInt(3, record.value);
    ps.addBatch();
}
ps.executeBatch();

我只是想知道上面的代码是否等同于下面的代码。如果不是,哪个更快

String query = "INSERT INTO table (id, name, value) VALUES ";
for (Record record : records) {
    query += "(" + record.id + ",'" + record.name + "'," + record.value + "),";
}
query = query.substring(1, query.length() - 1);
PreparedStatement ps = connection.prepareStatement(query);
ps.executeUpdate();

共 (6) 个答案

  1. # 1 楼答案

    如果您的记录大小小于或等于1000,则以下代码优于这两种代码:

    StringBuilder query = new StringBuilder("INSERT INTO table (id, name, value) VALUES ");
    
    if (records.size() <= 1000) {
        
        for (int i = 0; i < records.size(); i++)
            query.append("(?, ?, ?), ");
    
        query = new StringBuilder(query.substring(1, query.length() - 1));
    
        PreparedStatement ps = connection.prepareStatement(query.toString());
    
        for (int i = 0; i < records.size(); i++) {
            ps.setInt((i * 3) + 1, record.id);
            ps.setString((i * 3) + 2, record.name);
            ps.setInt((i * 3) + 3, record.value);
        }
        
        ps.executeUpdate();
        
    }
    

    这样,您就可以使用PreparedStatement,并在一个insert查询中使用多个values子句根据记录列表的大小动态创建它

  2. # 2 楼答案

    首先,使用查询字符串连接,不仅会丢失PreparedStatement方法本机的类型转换,而且还容易受到数据库中执行的恶意代码的攻击

    第二,PreparedStatements以前缓存在数据库本身中,这已经比普通语句有了很好的性能改进

  3. # 3 楼答案

    我想这个就行了

    String query = "INSERT INTO table (id, name, value) VALUES ";
    for (Record record : records)
    {
    query += "(" + record.id + ",'" + record.name + "'," + record.value + "),";
    query = query.substring(1, query.length() - 1);
    PreparedStatement ps = connection.prepareStatement(query);
    ps.executeUpdate();
    }
    

    因为您必须对每个要插入数据库的记录执行查询

  4. # 4 楼答案

    关闭自动提交

    只要将autocommit设置为false,那么executeBatch将比executeUpdate具有更好的性能:

    connection.setAutoCommit(false);  
    PreparedStatement ps = connection.prepareStatement(query);            
    for (Record record : records) {
        // etc.
        ps.addBatch();
    }
    ps.executeBatch();
    connection.commit(); 
    
  5. # 5 楼答案

    如果要插入的项目数量很大,则可能会面临严重的性能问题。因此,更安全的做法是定义批量大小,并在达到批量大小时持续执行查询

    下面的示例代码应该可以使用。有关如何有效地使用此代码的完整故事,请参见link

    private static void insertList2DB(List<String> list) {
            final int batchSize = 1000; //Batch size is important.
            Connection conn = getConnection();
            PreparedStatement ps = null;
            try {
                String sql = "INSERT INTO theTable (aColumn) VALUES (?)";
                ps = conn.prepareStatement(sql);
    
                int insertCount=0;
                for (String item : list) {
                    ps.setString(1, item);
                    ps.addBatch();
                    if (++insertCount % batchSize == 0) {
                        ps.executeBatch();
                    }
                }
                ps.executeBatch();
    
            } catch (SQLException e) {
                e.printStackTrace();
                System.exit(1);
            }
        finally {
            try {
                ps.close();
                conn.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    } 
    
  6. # 6 楼答案

    public void insertBatch(final List<Record > records ) {
    
        String query = "INSERT INTO table (id, name, value) VALUES (?, ?, ?)";
    
    
        GenericDAO.getJdbcTemplate().batchUpdate(sql, new BatchPreparedStatementSetter() {
    
    
            @Override
            public void setValues(PreparedStatement ps, int i) throws SQLException {
                  Record record = records .get(i);
                  ps.setInt(1, record.id);
                  ps.setString(2, record.name);
                  ps.setInt(3, record.value);
            }
    
            @Override
            public int getBatchSize() {
                return records.size();
            }
        });
    }