JDBC(Statement & PreparedStatement)

Statement:

创建数据库:

创建表:

插入数据:

查询数据:

Statement 会引入 SQL 注入问题:

PreparedStatement:

通常我们执行一条 SQL 语句,得经过下面三个过程。

1. 词法和语义解析

2. 优化 SQL 语句,制定执行计划

3. 执行并返回结果

编译:

执行:

删除:

SQL代码:

# 预编译语句 
# 编译 
prepare ps from 'select * from t_user where name=? and password=?';
# 设置参数 
set @name='Thomas_He';
set @password='123456';
# 执行
execute ps using @name, @password;
# 删除 
drop prepare ps;

Java 中我们提供了 PreparedStatement 这个接口来调用数据库的预编译功能。

public class PrepareStatementDemo {
    //java预编译
    @Test
    public void testInjection() throws SQLException {
        Connection conn = getConnection();
        String sql = "select * from t_user where name=? and password=?";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        // 设置参数
        String name = "aaa' or 1=";
        String password = " or 1='1";
        name = "'" + name + "'";
        password = "'" + password + "'";
        pstmt.setString(1, name);
        pstmt.setString(2, password);
        // 执行
        ResultSet rs = pstmt.executeQuery();
        // 处理结果集
        while (rs.next()) {
            String username = rs.getString("name");
            BigDecimal balance = rs.getBigDecimal("balance");
            System.out.println(username + ": " + balance);
        }
    }
    //测试java预编译的性能(发现差别并不大,因为消耗的时间主要来自于网络通信)
    @Test
    public void testPerformance() throws SQLException { //23673ms
        Connection conn = getConnection();
        String sql = "insert into t_user(name, password) values(?, ?)";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 20000; i++) {
            pstmt.setString(1, "user" + i);
            pstmt.setString(2, "123456");
            pstmt.executeUpdate();
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start + "ms");
    }
    //连接的方法
    private Connection getConnection() {
        Properties info = new Properties();
        try (Reader reader = new FileReader("db.properties")) {
            info.load(reader);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String url = info.getProperty("url");
        String user = info.getProperty("user");
        String password = info.getProperty("password");
        Connection conn = null;
        try {
            conn = DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }
}

只会把它当做参数,不是当做逻辑处理(所以能够避免sql注入)

批处理:batch

pstmt.addBatch();
pstmt.executeBatch();
pstmt.clearBatch();

ResultSet

    @Test
    public void testTransaction() throws SQLException {
        Connection conn = getConnection();
        String sql = "update t_user set balance = balance - 100 where id=?";
        PreparedStatement pstmt1 = conn.prepareStatement(sql);
        pstmt1.setInt(1, 1);
        // 开启事务
        conn.setAutoCommit(false);
        pstmt1.executeUpdate();
        System.out.println(1/0);
        sql = "update t_user set balance = balance + 100 where id=?";
        PreparedStatement pstmt2 = conn.prepareStatement(sql);
        pstmt2.setInt(1, 2);
        pstmt2.executeUpdate();
        // 提交事务
        conn.commit();
    }

猜你喜欢

转载自blog.csdn.net/weixin_41988545/article/details/106566567