通过将多个 UPDATE 或 INSERT 语句分组为一个批处理,将整个批处理发送到数据库并一起处理,可以减少数据库的往返处理次数,从而提高应用程序性能。

OceanBase Connector/J 使用服务器 PrepareStatement 和 Statements 作为与数据库进行批处理通信的标准,并通过 allowMultiQueries 和 rewriteBatchedStatements 两个参数进行管理。如果将 allowMultiQueries 或 rewriteBatchedStatements 选项设置为 true,则 OceanBase Connector/J 将仅使用文本协议。PrepareStatement(参数替换)在客户端由驱动程序处理。
rewriteBatchedStatements 对于插入查询,用于重写 batchedStatement 以在单个 executeQuery 中执行。当它处于活跃状态时,useServerPrepStmts 选项被设置为 false。allowMultiQueries 为 true 时允许多值查询。
在 Oracle 和 MySQL 两种模式下,OceanBase Connector/J 对于批处理的设置会有不同。
PrepareStatement 处理方式
| useServerPrepStmts | rewriteBatchedStatements | allowMultiQueries | INSERT 操作 | UPDATE 操作 | 
|---|---|---|---|---|
| true | true | true | Prepare 的 SQL String 会变成  | Prepare 的 SQL String 是正常格式,之后通过多次 | 
| true | false | Prepare 的 SQL String 会变成  | Prepare 的 SQL String 是正常格式,之后通过多次 | |
| false | true | Prepare 的 SQL String是正常格式,之后通过多次  | Prepare 的 SQL String是正常格式,之后通过多次 | |
| false | false | Prepare 的 SQL String 是正常格式,之后通过多次 | Prepare 的 SQL String 是正常格式,之后通过多次 | |
| false | true | true | 拼成一个完整的  | 拼成一个完整的  | 
| true | false | 拼成一个完整的  | 执行多条  | |
| false | true | 执行多条  | 执行多条  | |
| false | false | 执行多条  | 执行多条  | 
Statement 处理方式
| useServerPrepStmts | rewriteBatchedStatements | allowMultiQueries | INSERT 操作 | UPDATE 操作 | 
|---|---|---|---|---|
| true | true | true | SQL String 会变成  | SQL String 会变成  | 
| true | false | 逐一执行 SQL。 | 逐一执行 SQL。 | |
| false | true | SQL String 会变成  | SQL String 会变成  | |
| false | false | 逐个执行  | 逐个执行  | |
| false | true | true | SQL String 会变成  | SQL String 会变成  | 
| true | false | 逐一执行 SQL。 | 逐一执行 SQL。 | |
| false | true | SQL String 会变成  | SQL String 会变成  | |
| false | false | 逐一执行  | 逐一执行  | 
PrepareStatement 处理方式
| useServerPrepStmts | rewriteBatchedStatements | allowMultiQueries | INSERT 操作 | UPDATE 操作 | 
|---|---|---|---|---|
| true | true | true | SQL String 会变成  | 逐一 Prepare 的 SQL String 是正常格式,之后通过多次  | 
| true | false | SQL String 会变成  | 逐一 Prepare 的 SQL String 是正常格式,之后通过多次  | |
| false | true | Prepare 的 SQL String 是正常格式,之后通过多次  | Prepare 的 SQL String 是正常格式,之后通过多次  | |
| false | false | Prepare 的 SQL String 是正常格式,之后通过多次  | Prepare 的 SQL String 是正常格式,之后通过多次  | |
| false | true | true | 拼成一个完整的  | 拼成一个完整的  | 
| true | false | 拼成一个完整的  | 执行多条  | |
| false | true | 执行多条  | 执行多条  | |
| false | false | 执行多条  | 执行多条  | 
Statement 处理方式
| useServerPrepStmts | rewriteBatchedStatements | allowMultiQueries | INSERT 操作 | UPDATE 操作 | 
|---|---|---|---|---|
| true | true | true | SQL String 会变成  | SQL String 会变成  | 
| true | false | 逐一执行 SQL。 | 逐一执行 SQL。 | |
| false | true | SQL String 会变成  | SQL String 会变成  | |
| false | false | 逐一执行  | 逐一执行  | |
| false | true | true | SQL String 会变成  | SQL String 会变成  | 
| true | false | 逐一执行 SQL。 | 逐一执行 SQL。 | |
| false | true | SQL String 会变成  | SQL String 会变成  | |
| false | false | 逐一执行  | 逐一执行  | 
public void test_execute_batch() {
    Connection conn = null;
    try {
        for (int q = 0; q < 2; q++) {
            for (int w = 0; w < 2; w++) {
                for (int e = 0; e < 2; e++) {
                    /**
                     *  useServerPrepStmts = true / false
                     *  rewriteBatchedStatements = true / false
                     *  allowMultiQueries = true / false
                     */
                    boolean uSPS = q == 0 ? false : true;
                    String rBS = w == 0 ? "false" : "true";
                    String aMQ = e == 0 ? "false" : "true";
                    String other_condition = "&rewriteBatchedStatements=" + rBS
                            + "&allowMultiQueries=" + aMQ;
                    conn = ConnectionUtils.getDefObOracleConnection(uSPS, true, other_condition);
                    Statement statement = conn.createStatement();
                    try {
                        statement.execute("DROP TABLE test_batch_t");
                    } catch (SQLException exp) {
                        //e.printStackTrace();
                    }
                    String sql = "create table test_batch_t(id int primary key, c1 varchar2(10))";
                    statement.execute(sql);
                    PreparedStatement ps = conn
                            .prepareStatement("insert into test_batch_t(id, c1) values (?, ?)");
                    for (int j = 0; j < 10; j++) {
                        ps.setInt(1, j);
                        ps.setString(2, j + "_test");
                        ps.addBatch();
                    }
                    ps.executeBatch();
                    ps = conn.prepareStatement("update test_batch_t set id = ? where c1 = ?");
                    for (int j = 0; j < 10; j++) {
                        ps.setInt(1, j);
                        ps.setString(2, j + "_test");
                        ps.addBatch();
                    }
                    ps.executeBatch();
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}