首页 > 其他分享 >JDBC之Statement和ResultSet

JDBC之Statement和ResultSet

时间:2022-12-18 23:45:09浏览次数:42  
标签:JDBC name resultSet ResultSet Statement SQL id String

Statement和ResultSet

目录

Statement

Statement概述

接口的实现在数据库驱动中. 用来操作sql语句(增删改查),并返回相应结果对象

JDBC利用Statement把将要执行的SQL发送给MySQL服务端进行操作。

JDBC利用Statement把将要执行的SQL发送给MySQL服务端进行操作。

JDBC利用Statement把将要执行的SQL发送给MySQL服务端进行操作。

JDBC想要利用SQL完成对数据库的增删改查,只需要通过Statement这个对象向数据库发送增删改查对应的SQL语句即可。

要执行的SQL分为两类

查询

Statement.executeQuery方法用于向数据库发送查询语句,executeQuery方法返回代表查询结果的ResultSet对象。

增删改

Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sql语句,executeUpdate执行完后,将会返回一个整数(即增删改对应的SQL语句导致了数据库有几行数据发生了变化)。

Statement继承体系

其中 CallableStatement 继承自 PreparedStatement, 而 PreparedStatement 又继承自 Statement。

他们的区别是:

名称 Statement PreparedStatement CallableStatement
说明 Statement 提供基本的 SQL 操作. 适合静态SQL语句, 且传入的 SQL 语句无法接受参数. PreparedStatement 可以在 SQL 中传递参数, 适合多次使用的 SQL 语句. CallableStatement 可以调用 PL/SQL 存储过程.
使用 select * from account select * from account where id = ?
额外说明 静态SQL,因为没有动态参数 动态SQL
可以防止SQL注入
不做了解,因为阿里巴巴规范中强制要求不要使用存储过程

SQL注入问题

下面先看下SQL注入出现的原因,代码如下:

public class SqlInjectTest {
    public static void main(String[] args) throws SQLException {
        String url = "jdbc:mysql://localhost:3306/mysql_index_test?useSSL=true";
        Properties properties = new Properties();
        properties.setProperty("user","root");
        properties.setProperty("password","root");
        Connection connection = DriverManager.getConnection(url, properties);
        Statement statement = connection.createStatement();
        // 后面的参数1假如是用户传递的
        String paremeter = "1";
        String sql = "select * from film where id = " + paremeter;
        ResultSet resultSet = statement.executeQuery(sql);
        while (resultSet.next()){
            int id = resultSet.getInt("id");
            String name = resultSet.getString("name");
            System.out.println(String.format("id是:%s,name是:%s",id,name));
        }
        resultSet.close();
        statement.close();
        connection.close();
    }
}

查询结果如下:

id是:1,name是:film1

但是如果被有些别出心裁的人知道了SQL语句是这样子拼接的时候,那么可以伪造SQL,如下所示:

public class SqlInjectTest {
    public static void main(String[] args) throws SQLException {
        String url = "jdbc:mysql://localhost:3306/mysql_index_test?useSSL=true";
        Properties properties = new Properties();
        properties.setProperty("user","root");
        properties.setProperty("password","root");
        Connection connection = DriverManager.getConnection(url, properties);
        Statement statement = connection.createStatement();
        // 后面的参数1假如是用户传递的
        String paremeter = "1 or 1=1";
        String sql = "select * from film where id = " + paremeter;
        ResultSet resultSet = statement.executeQuery(sql);
        while (resultSet.next()){
            int id = resultSet.getInt("id");
            String name = resultSet.getString("name");
            System.out.println(String.format("id是:%s,name是:%s",id,name));
        }
        resultSet.close();
        statement.close();
        connection.close();
    }
}

对应的结果如下所示:

id是:3,name是:film0
id是:1,name是:film1
id是:2,name是:film2

SQL注入问题解决

本质原因是因为上面使用的Statement是原生的,那么我们需要使用预编译的PreparedStatement解决问题

代码如下所示:

public class SqlInjectTest {
    public static void main(String[] args) throws SQLException {
        String url = "jdbc:mysql://localhost:3306/mysql_index_test?useSSL=true";
        Properties properties = new Properties();
        properties.setProperty("user","root");
        properties.setProperty("password","root");
        Connection connection = DriverManager.getConnection(url, properties);
        // 后面的参数1假如是用户传递的
        String paremeter = "film0";
        String sql = "select * from film where name = ?" ;
        PreparedStatement statement = connection.prepareStatement(sql);
        // 设置第1个?的值是paremeter
        statement.setString(1,paremeter);
        ResultSet resultSet = statement.executeQuery();
        while (resultSet.next()){
            int id = resultSet.getInt("id");
            String name = resultSet.getString("name");
            System.out.println(String.format("id是:%s,name是:%s",id,name));
        }
        resultSet.close();
        statement.close();
        connection.close();
    }
}

那么再看一下另外一种情况

public class SqlInjectTest {
    public static void main(String[] args) throws SQLException {
        String url = "jdbc:mysql://localhost:3306/mysql_index_test?useSSL=true";
        Properties properties = new Properties();
        properties.setProperty("user","root");
        properties.setProperty("password","root");
        Connection connection = DriverManager.getConnection(url, properties);
        // 后面的参数1假如是用户传递的
        String paremeter = "film0 or 1=1";
        String sql = "select * from film where name = ?" ;
        PreparedStatement statement = connection.prepareStatement(sql);
        // 设置第1个?的值是paremeter【根据对应的数据类型来进行设置】
        statement.setString(1,paremeter);
        ResultSet resultSet = statement.executeQuery();
        while (resultSet.next()){
            int id = resultSet.getInt("id");
            String name = resultSet.getString("name");
            System.out.println(String.format("id是:%s,name是:%s",id,name));
        }
        resultSet.close();
        statement.close();
        connection.close();
    }
}

没有结果!!!

因为对应的SQL已经被修改了,变成了

select * from film where name = 'film0 or 1=1'

而不是我们想象的

select * from film where name = 'film0' or 1=1

所以上面的查询是没有结果的,因为在数据库中根本就没有找到这样的name

ResultSet

从名字上就可以看到是结果集,表示的是查询出来的结果集。

JDBC用ResultSet来封装结果集,查询结果表的对象。

查询结果分为两种情况:

单值

单个结果,比如说SQL如下:

select count(*) from account;
select max(id) from account;
select min(id) from account;

查询出来的是一个数字

多值

普遍来说是多个字段,这个时候对象就可以发挥效果。

select id,name,address from account where id = 1;

重点

游标

在ResultSet有一个游标的概念

提供一个游标,默认游标指向结果集第一行之前。调用一次next(),游标向下移动一行。提供一些get方法。

根据while循环的使用经验,如果不知道有多少条,那么使用while进行判断即可。

get方法

既然获取出来的有结果,那么就需要得到对应的值。ResultSet也提供了对应的方法

ResultSet接口常用API

  • boolean next();将光标从当前位置向下移动一行
  • int getInt(int colIndex)以int形式获取ResultSet结果集当前行指定列号值
  • int getInt(String colLabel)以int形式获取ResultSet结果集当前行指定列名值
  • float getFloat(int colIndex)以float形式获取ResultSet结果集当前行指定列号值
  • float getFloat(String colLabel)以float形式获取ResultSet结果集当前行指定列名值
  • String getString(int colIndex)以String 形式获取ResultSet结果集当前行指定列号值
  • String getString(String colLabel)以String形式获取ResultSet结果集当前行指定列名值
  • Date getDate(int columnIndex); 以Date 形式获取ResultSet结果集当前行指定列号值
  • Date getDate(String columnName);以Date形式获取ResultSet结果集当前行指定列名值
  • void close()关闭ResultSet 对象

使用示例

public class User implement Serializable{

    private int id;
    private String username;
    private String password;
    private String nickname;

    //提供get/set/toString方法 Alt+Insert
}

对应的JDBC代码如下所示

List<User> list = new ArrayList<User>();

while (resultSet.next()) {
    //每遍历一次, 就是1条记录, 就封装成一个User对象
    User user = new User(resultSet.getInt("id"),
    resultSet.getString("username"),
    resultSet.getString("password"),
    resultSet.getString("nickname")
);
list.add(user);

}

标签:JDBC,name,resultSet,ResultSet,Statement,SQL,id,String
From: https://www.cnblogs.com/likeguang/p/16991281.html

相关文章

  • cppconn resultsetmetadata get columns count,get column name,resultset get value
    //Model/mysqlhelper.h#ifndef__mysqlhelper_h__#define__mysqlhelper_h__#include<chrono>#include<ctime>#include<fstream>#include<iomanip>#include<i......
  • JDBC之Connection
    Connection目录ConnectionJava连接MySQLConnection必备知识点利用JDBC使用Connection问题一:为什么Java操作数据库的连接不是越多越好问题二、数据库最多支持多少Connectio......
  • JDBC之Driver和DriverMananger
    JDBC之Driver和DriverMananger目录JDBC之Driver和DriverManangerJava和MySQL的关系JDBC演变过程驱动加载入内存的过程Oracle加载驱动的静态方法MySQL加载驱动的静态方法Dr......
  • JDBC
    JDBC:java连接数据库固定步骤加载驱动连接数据库向数据库发送SQL的对象Statement:CRUD编写SQL(根据业务编写不同的SQL语句)执行SQL关闭连接注:在数据库的编写之中尽量的采用pr......
  • MVC、三层架构、数据库连接池、Spring JDBC
    MVC模式MVC全名是ModelViewController,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻......
  • 关于PB用JDBC连接MySQL,亲测有效
        以前自学过一段时间的PB,数据窗口让人印象深刻,前段时间,在西瓜视频看到有人录制了PB的教学视频,让我想起以前自学的那段时光,遇到了问题,也不知道问谁,现在网......
  • JDBC_API详解
    DiverManager(驱动管理类)作用:①注册驱动②获取数据库链接Connection(数据库连接对象)作用:①获取执行sql的对象②管理事务获取SQL对象事务管理......
  • JDBC入门
    JDBC快速入门URL路径语法jdbc:mysql://ip地址(域名):端口号/数据库名称如果连接的是本机mysql服务器,并且mysql服务器默认端口是3306,则url可以缩写为:jdbc:mysql:///数......
  • maven缺失ojdbc6解决方法(手动安装ojdbc6)
    maven缺失ojdbc6解决方法(手动安装ojdbc6)1.首先下载ojdbc6jar包jar下载地址一(需登录)jar下载地址二(直接下载)2.进入到jar包所在文件夹,执行cmd命令cmd终端执行下面......
  • ssm报错Could not open JDBC Connection for transaction; nested exception is com.m
    HTTPStatus500-Requestprocessingfailed;nestedexceptionisorg.springframework.transaction.CannotCreateTransactionException:CouldnotopenJDBCConnecti......