首先关于Statement和PreparedStatement的基本概念我就不再叙述了,可以参考这篇文章,下面我们来看几个测试例子吧。

测试场景

现在我们向数据库中的一张表中插入100000(10万)条数据,测试使用Statement和PreparedStatement及PreparedStatement的Batch方式所需要的时间。

Dao基类

/**
 * 
 * Description: 数据库操作基类
 *
 * @author: crane-yuan
 * @date: 2016年9月27日 下午1:40:04
 */
public class BaseDao {
    protected Connection connection; // 访问数据库的句柄
    public void openConnection() throws Exception {
        if (this.connection == null || this.connection.isClosed()) {
            try {
                DbInfo dbinfo = DbInfo.instance();
                Class.forName(dbinfo.getDbdriver()); // 加载oracle的驱动
                connection = DriverManager.getConnection(dbinfo.getUrl(),
                        dbinfo.getUser(), dbinfo.getPassword());
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                System.out.println("请检查驱动包是否正确");
                throw e;
            } catch (SQLException e) {
                e.printStackTrace();
                System.out.println("请检查数据库的配置项是否正确");
                throw e;
            }
        }
    }
    public void closeConnection() throws Exception {
        if (this.connection != null) {
            this.connection.close();
        }
    }
} 

Statement方式

/**
 * 
 * Description: 测试Statement
 *
 * @throws Exception void
 */
public void testStatement() throws Exception {
    System.out.println("--------------Statement no batch----------------");
    String sql = "";
    this.openConnection();
    // 手动提交
    this.connection.setAutoCommit(false);
    Statement statement = this.connection.createStatement();
    Long beginTime = System.currentTimeMillis();
    System.out.println(new Date(beginTime));
    try {
        for (int i = 100001; i < 200000; i++) {
            sql = "insert into testStatement(code) values(" + i + ")";
            statement.executeUpdate(sql);
        }
    } catch (SQLException exception) {
        exception.printStackTrace();
    }
    this.connection.commit();
    statement.close();
    this.connection.close();
    Long endTime = System.currentTimeMillis();
    System.out.println(new Date(endTime));
    System.out.println("Statement:" + (endTime - beginTime) / 1000 + "秒");
}

结果:

--------------Statement no batch----------------
Wed Oct 19 16:42:22 CST 2016
Wed Oct 19 16:46:32 CST 2016
Statement:249

PreparedStatement无Batch方式

/**
 * 
 * Description: 测试PreparedStatement,不开启Batch提交
 *
 * @throws Exception void
 */
public void testPreparedStatement() throws Exception {
    System.out
            .println("--------------PreparedStatement no batch----------------");
    String sql = "insert into testStatement(code) values(?)";
    this.openConnection();
    // 手动提交
    this.connection.setAutoCommit(false);
    PreparedStatement ps = this.connection.prepareStatement(sql);
    Long beginTime = System.currentTimeMillis();
    System.out.println(new Date(beginTime));
    try {
        for (int i = 0; i < 100000; i++) {
            String code = "" + i;
            ps.setString(1, code);
            ps.execute();
        }
    } catch (SQLException exception) {
        exception.printStackTrace();
    }
    this.connection.commit();
    ps.close();
    this.connection.close();
    Long endTime = System.currentTimeMillis();
    System.out.println(new Date(endTime));
    System.out.println("PreparedStatement:" + (endTime - beginTime) / 1000 + "秒");
}

结果

--------------PreparedStatement no batch----------------
Wed Oct 19 16:46:32 CST 2016
Wed Oct 19 16:48:37 CST 2016
PreparedStatement:125

PreparedStatement有Batch方式

/**
 * 
 * Description: 测试使用PreparedStatement,并且开启Batch提交.
 *
 * @throws Exception void
 */
public void testPreparedStatementBatch() throws Exception {
    System.out
            .println("--------------PreparedStatement with batch----------------");
    String sql = "insert into testStatement(code) values(?)";
    this.openConnection();
    // 手动提交
    this.connection.setAutoCommit(false);
    PreparedStatement ps = this.connection.prepareStatement(sql);
    Long beginTime = System.currentTimeMillis();
    System.out.println(new Date(beginTime));
    int count = 0;
    try {
        for (int i = 200001; i < 300000; i++) {
            String code = "" + i;
            ps.setString(1, code);
            ps.addBatch();
            count++;
            if (count == 500) {
                count = 0;
                ps.executeBatch();
                this.connection.commit();
                ps.clearBatch();
            }
        }
    } catch (SQLException exception) {
        exception.printStackTrace();
    }
    ps.close();
    this.connection.close();
    Long endTime = System.currentTimeMillis();
    System.out.println(new Date(endTime));
    System.out.println("PreparedStatement+batch:" + (endTime - beginTime) / 1000 + "秒");
}

结果

--------------PreparedStatement with batch----------------
Wed Oct 19 16:48:37 CST 2016
Wed Oct 19 16:48:38 CST 2016
PreparedStatement+batch:1

总结

一般来说,PreparedStatement的Batch方式执行效率比PreparedStatement和Statement的都高,PreparedStatement无Batch方式比Statement方式也要高。
在实际开发中一般推荐使用PreparedStatement,不过PreparedStatement也有一些缺点,在这篇文章中暂时不在叙述了,这方面的对比将在下篇文章中详细讲解。


本文转载:CSDN博客