JDBC-Statement和PreparedStatement

1.Statement

1.1 具体步骤

1.注册驱动
2.获取连接
3.创建发送sql语句对象
4.发送sql语句并得到返回结果
5.对得到的结果集进行解析
6.释放资源(包括结果集 连接 驱动)

1.2 简单实例

数据库中当前存在以下数据:在这里插入图片描述

//创建数据库连接 模拟用户输入用户名和密码 在数据库中查询该用户是否存在 如果存在则输出用户信息
public class statementQuery {
    public static void main(String[] args) throws SQLException {
        //用户输入账号和密码
        Scanner scanner = new Scanner(System.in);
        String account = scanner.nextLine();
        String password = scanner.nextLine();
        scanner.close();
        //1.注册驱动
        DriverManager.registerDriver(new Driver());
        //2.创建连接
        Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/atguigu", "root", "123456");
        Statement statement = connection.createStatement();
        //3.创建发送sql语句对象
        String sql = "select * from t_user where account = '" + account + "' and password = '" + password + "' ;";
        //4.发送sql语句并得到返回结果
        ResultSet resultSet = statement.executeQuery(sql);
        //5.结果集解析
        if (resultSet.next()) {
            int id = resultSet.getInt("id");
            String account1 = resultSet.getString("account");
            String password1 = resultSet.getString("password");
            String nickname = resultSet.getString("nickname");
            System.out.println("id:" + id + "  account:" + account1 + "  password:" + password1 + "  nickname :" + nickname);
        } else {
            System.out.println("用户不存在");
        }
        //6.关闭资源
        resultSet.close();
        statement.close();
        connection.close();
    }
}

1.3 对核心API的解释说明

1.注册驱动
使用 DriverManager.registerDriver(new Driver());会注册两次驱动,造成不必要的资源浪费
使用反射的方法进行驱动注册: Class.forName("com.mysql.cj.jdbc.Driver");

2.获取连接(3种方法)
  url:连接数据库的地址(形式如下所示)
      jdbc:数据库类别://IP地址:端口号/数据库名
      jdbc:mysql://127.0.0.1:3306/atguigu
      jdbc:mysql://localhost:3306/atguigu (127.0.0.1=localhost)
      jdbc:mysql:///atguigu (IP地址是当前电脑且端口号是3306时可以这样写)
  user:连接数据库用户名
  password:连接数据库密码
  
  2.1 getConnection(String url,String user, String password)
      getConnection("jdbc://localhost:3306/atguigu","root","123456");
      
  2.2 getConnection(String url,java.util.Properties info)
       Properties : 是一个参数封装容器!至少要包含 user / password 存储连接账号信息
       Properties properties=new Properties();
       properties.put("user","root");
       properties.put("password","123456");
       getConnection("jdbc://localhost:3306/atguigu",properties);
       
  2.3 getConnection(String url)
      URl可以携带目标地址,可以通过?分割,在后面key=value&key=value形式传递参数
      getConnection("jdbc://localhost:3306/atguigu?user=root&password=123456");
      
3. 发送sql语句并得到查询结果
   3.1 ResultSet executeQuery(String sql)  
       其中sql只能是DQL,对数据库进行查询,返回的是封装的结果集对象
       
   3.2 int executeUpdate(String sql)
       3.2.1 sql是DML语句 返回影响的行数,如修改2条则返回2,删除1条则返回1
       3.2.2 sql语句是非DMLDQL语句,返回值始终是0
       
5. 对结果进行解析
   get类型(int columnIndex | String columnLabel)
   columnLabel:如果没有别名,等于列名,有别名就是别名
   columnIndex:从左到右 从1开始
       
   int id = resultSet.getInt(1); = int id = resultSet.getInt("id");
   String account1 = resultSet.getString(2); =  String account1 = resultSet.getString("account");
   String password1 = resultSet.getString(3); = String password1 = resultSet.getString("password");
   String nickname = resultSet.getString(4); = String nickname = resultSet.getString("nickname");           

2. PreparedStatement

  • Statement 安全隐患—注入攻击
    Statement 在执行 sql 语句时都会把表单提交来的 用户名 和 密码 都重新拼接到 sql 语句中,然后再执行,这样会导致 sql 语句结构发生改变。
String sql = "select * from t_user where account = '" + account + "' and password = '" + password + "' ;";
当登录的时候用户输入 1' OR '1'='1 也可以登陆成功,此时sql变成如下所示:
sql = "select * from t_user where account = '" + account + "' and password = '1' OR '1'='1' ;";
此时会将原表中所有的信息都查询到,因为where后面的子句是true,如果按照Statement中的代码,最终会输出第一行数据信息。
  • 占位符如何避免了注入攻击
    当使用占位符时,数据库引擎会将查询和提供给占位符的值视为两个分离的部分。
SELECT * FROM users WHERE username = ?

若用户恶意输入’admin’ OR 1=1。假如不使用占位符,则SQL语句如下

SELECT * FROM users WHERE username = 'admin' OR 1=1'

1=1恒为真,数据库会返回所有的user行,因为数据库将1=1视为bool值进行了判断。但是若使用了占位符,数据库会将所有的输入视为普通的文本输入,而不会进行bool值判断,即不再会判断1=1是否为真,而是只是将其视为简单的文本输入。

2.1 具体步骤

注意与Statement的区别在于3456,先编写sql语句结构并传给PerparedStatement保证了结构的确定性,可以避免出现注入攻击

1.注册驱动
2.建立连接
3.编写动态sql语句结构,动态值使用 ? 代替
4.创建PerparedStatememt,并传入动态sql语句
5.给动态值赋值
6.发送sql语句并获得返回结果
7.对返回结果集进行解析
8.释放资源(包括结果集、连接、驱动)

2.2 简单实例

//创建数据库连接 模拟用户输入用户名和密码 在数据库中查询该用户是否存在 如果存在则输出用户信息
public void testQuery() throws Exception {
        Scanner scanner = new Scanner(System.in);
        String account = scanner.nextLine();
        String password = scanner.nextLine();
        scanner.close();
        //1.注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        //2.创建连接
        Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu?user=root&password=123456");
        //3.编写动态sql结构
        String sql = " select * from t_user where account=? and password=?;";
        //4.创建PerparedStatement并传入sql
        java.sql.PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //5.占位符赋值
        preparedStatement.setObject(1, account);
        preparedStatement.setObject(2, password);
        //6.执行sql语句并拿到结果集
        ResultSet resultSet = preparedStatement.executeQuery();
        //7.对结果集进行解析
        if (resultSet.next()) {
            int id = resultSet.getInt(1);
            String account1 = resultSet.getString(2);
            String password1 = resultSet.getString(3);
            String nickname = resultSet.getString(4);
            System.out.println("id:" + id + "  account:" + account1 + "  password:" + password1 + "  nickname :" + nickname);
        } else {
            System.out.println("用户不存在");
        }
        //8.关闭资源
        resultSet.close();
        preparedStatement.close();
        connection.close();
    }
//插入一条数据
public void testInsert() throws Exception {
        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu?user=root&password=123456");
        String sql="insert into t_user(account,password,nickname) values(? ,?, ?)";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setObject(1,"zhangsan");
        preparedStatement.setObject(2,"999999");
        preparedStatement.setObject(3,"员工");
        int resultSet = preparedStatement.executeUpdate();
        if(resultSet>0){
            System.out.println("插入数据成功");
        }else {
            System.out.println("插入数据失败");
        }
        preparedStatement.close();
        connection.close();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值