PreparedStatement VS Statement

联系:

PreparedStatement 接口是 Statement 的子接口,都可用来SQL查询

区别:

1.代码的可读性和可维护性. Statement 的 sql 拼接属实恶心心~
2.PreparedStatement 可以防止 SQL 注入
3.PreparedStatement 可以处理 Blob 类型的数据
4.PreparedStatement 能最大可能提高性能:(Oracle 和 PostgreSQL8 是这样,但是对于 MySQL 不一定比 Statement 高)

第一条没什么好说的,放两个实例大家看一下都知道用哪个了。
Statement 恶心的拼串,字段不多,可能没恶心到你,对不起~
在这里插入图片描述

PreparedStatement预编译的SQL

在这里插入图片描述
如果没能恶心到你,的确,繁琐的拼串还能让人接受,但是SQL注入问题,Statement 解决不了!

SQL注入:
SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或 命令,从而利用系统的 SQL 引擎完成恶意行为的做法。对于 Java 而言,要防范 SQL 注入,只要用 PreparedStatement 取代 Statement 就可以了。

还是举个栗子~
还是拿用户名和密码来说,比如user表有一条数据,用户名:admin 密码为:admin 如果此时你用的Statement拼串方式,用户把密码写成admin’ or ‘1’ = ‘1 那么此时的sql就为:
select * from user where username=‘admin’ and paaword =’ admin’ or ‘1’ = '1 ’ 就会非法登录成功!

处理BLOB字段
BLOB (binary large object),二进制大对象,BLOB 常常是数据库中用来存储二进制文件的字段类型。 插入 BLOB 类型的数据必须使用 PreparedStatement,因为 BLOB 类型的数据无法使用字符串拼接写的。这一点Statement做不到

提高性能
DBServer 会对预编译语句提供性能优化。因为预编译语句有可能被重复调用,所以语句在被 DBServer 的编 译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数 直接传入编译过的语句执行代码中就会得到执行。 
在 statement 语句中,即使是相同操作但因为数据内容不一样,所以整个语句本身不能匹配,没有缓存语句的 意义.事实是没有数据库会对普通语句编译后的执行代码缓存.这样每执行一次都要对传入的语句编译一次.  (语法检查,语义检查,翻译成二进制命令,缓存)

Statement不用,就写几个实例对PreparedStatement批量操作进行优化吧,感兴趣可以自己试一下这两个效率的差别~

public void isTest()  {
    Connection connection=null;
    PreparedStatement ps =null;
    try {
        long start = System.currentTimeMillis();
        connection = JDBCUtils.getConnection();
        String sql = "insert into student(id,name)values(?,?)";
        ps = connection.prepareStatement(sql);
        for (int i = 0; i <=20000 ; i++) {
            ps.setInt(1,i);
            ps.setString(2,"name"+i);
            ps.execute();
        }
        long end = System.currentTimeMillis();
        System.out.println("花费时间为:"+(end-start));
    } catch (SQLException e) {
        e.printStackTrace();
    }finally {
        JDBCUtils.closeQuietly(ps, connection);
    }
}

不做优化批量插入的时间:
在这里插入图片描述
简单优化:

public void isTest()  {
    Connection connection=null;
    PreparedStatement ps =null;
    try {
        long start = System.currentTimeMillis();
        connection = JDBCUtils.getConnection();
        String sql = "insert into student(id,name)values(?,?)";
        ps = connection.prepareStatement(sql);
        for (int i = 1; i <=20000 ; i++) {
            ps.setInt(1,i);
            ps.setString(2,"name"+i);

            //积攒sql
            ps.addBatch();

            if(i%5000==0){
                //执行batch
                ps.executeBatch();
                //清空batch
                ps.clearBatch();
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("花费时间为:"+(end-start));
    } catch (SQLException e) {
        e.printStackTrace();
    }finally {
        JDBCUtils.closeQuietly(ps, connection);
    }
}

还可以设置不自动提交,进一步优化:

public void isTest()  {
    Connection connection=null;
    PreparedStatement ps =null;
    try {
        long start = System.currentTimeMillis();
        connection = JDBCUtils.getConnection();
        //设置不允许自动提交数据
        connection.setAutoCommit(false);
        String sql = "insert into student(id,name)values(?,?)";
        ps = connection.prepareStatement(sql);
        for (int i = 1; i <=20000 ; i++) {
            ps.setInt(1,i);
            ps.setString(2,"name"+i);

            //积攒sql
            ps.addBatch();

            if(i%5000==0){
                //执行batch
                ps.executeBatch();
                //清空batch
                ps.clearBatch();
            }
        }
        //提交数据
        connection.commit();
        long end = System.currentTimeMillis();
        System.out.println("花费时间为:"+(end-start));
    } catch (SQLException e) {
        e.printStackTrace();
    }finally {
        JDBCUtils.closeQuietly(ps, connection);
    }
}

所需要的的时间:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值