## 模块3：使用预处理语句和批量插入

使用预处理语句，您可以预编译语句以重复执行。预处理语句可以帮助我们防止SQL注入。此外，当查询很长且复杂，和/或网络是瓶颈时，预处理语句可能会提高查询执行性能。

批量插入使用户能够在单个SQL语句中插入多行数据。

在本模块中，我们查看预处理语句和批量插入的示例。

### 步骤1. 使用预处理语句

+ 在左侧VS Code的**EXPLORER**部分，点击`DemoJdbcPreparedStatement.java`文件并阅读代码文件。

+ 使用预处理语句有两种方法。下面的第一个代码片段显示服务器端预处理语句。第二个代码块演示客户端预处理语句。在我们的示例中，您应该看到执行时间相似。

  ```java
  // Reuse PS
  connection.setAutoCommit(true);
  PreparedStatement update1_ps = connection.prepareStatement("UPDATE test.t1 SET name = ? WHERE id = 1");
  System.out.println(">>> Reuse PS Begin repeating update.");
  long s1 = System.currentTimeMillis();
  for (int i = 0; i < 200; i++) {
      update1_ps.setString(1, Integer.toString(i));
      update1_ps.executeUpdate();
  }
  update1_ps.close();
  ```

  ```java
  /**
  * Client side caching prepared statement, cache hit for prepareStatement and close.
  * Try set cachePrepStmts=false|true to see the difference on elapsed time.
  */
  PreparedStatement update2_ps = null;
  System.out.println(">>> Non-Reuse PS Begin repeating update.");
  long s2 = System.currentTimeMillis();
  for (int i = 0; i < 200; i++) {
      update2_ps = connection.prepareStatement("UPDATE test.t1 SET name = ? WHERE id = 1");
      update2_ps.setString(1, Integer.toString(i));
      update2_ps.executeUpdate();
      update2_ps.close();
  }
  ```

+ 您现在可以执行代码并查看结果。

  ```bash
  rm -f DemoJdbcPreparedStatement.class
  javac -cp mysql-connector-j-9.1.0.jar DemoJdbcPreparedStatement.java
  sleep 1
  java -cp :mysql-connector-j-9.1.0.jar DemoJdbcPreparedStatement
  ```

  ```output
  Connection established.
  >>> Reuse PS Begin repeating update.
  >>> End repeating update, elapsed: 4364(ms).
  >>> Non-Reuse PS Begin repeating update.
  >>> End repeating update, elapsed: 4225(ms).

  Executing query: select * from test.t1
          Row#, id, name
          1) 1, 199
  Turn on autocommit.
  Connection closed.
  ```

### 步骤2. 使用批量插入

+ 在左侧VS Code的**EXPLORER**部分，点击`DemoJdbcBatchInsert.java`文件。

+ 在此步骤中，我们将向表中插入1000行。我们将比较`rewriteBatchedStatements=true`和`rewriteBatchedStatements=false`之间的性能。

  ```bash
  rm -f DemoJdbcBatchInsert.class
  javac -cp mysql-connector-j-9.1.0.jar DemoJdbcBatchInsert.java
  sleep 1
  java -cp :mysql-connector-j-9.1.0.jar DemoJdbcBatchInsert
  ```

  ```output
  Connection established.
  >>> Begin insert 1000 rows.
  >>> End batch insert,rewriteBatchedStatements=true,elapsed: 172 (ms).
  Connection established.
  >>> Begin insert 1000 rows.
  >>> End batch insert,rewriteBatchedStatements=false,elapsed: 13252 (ms).

  /* Executing query: select count(*), max(name) from test.t1_batchtest; */
          Row#, count(*), max(name)
          1) 1000, 999
  Turn on autocommit.
  Connection closed.
  ```
