Java Jdbc的详解

Posted 路宇

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java Jdbc的详解相关的知识,希望对你有一定的参考价值。

一、Jdbc原理示意图

二、Jdbc的概述


三、JDBC的快速入门

代码如下,具体讲解在注释中已经说明

public class Jdbc01 
    public static void main(String[] args) throws SQLException 
        //前置工作:在项目下创建一个文件夹比如libs
        //将mysql.jar拷贝到该目录下,点击add to project ..加入到项目

        //1.注册驱动
        Driver driver = new Driver();//创建Driver对象

        //2.得到连接
        //解读
        //1.jdbc:mysql:// 规定好的协议,通过jdbc的方式连接mysql
        //2.localhost 主机,可以是ip地址
        //3.3306 表示sql监听的端口
        //4.db_ly 连接到mysql dbms的哪个数据库
        //5.mysql的连接本质就是socket连接
        String url = "jdbc:mysql://localhost:3306/db_ly?serverTimezone=GMT";

        //将用户名和密码放入到Properties对象
        Properties properties = new Properties();
        //说明 user 和 password 是规定好的,后面的值根据实际情况写
        properties.setProperty("user", "root");//用户
        properties.setProperty("password", "123456");//密码

        Connection connect = driver.connect(url, properties);

        //3.执行sql
//        String sql = "insert into actor values(null,'刘德华','男','1970-01-01','110')" +
//                ",(null,'周星驰','男','1980-01-03','123456789')";
        String sql = "update actor set name='王宝强' where id = 3";
//        String sql = "delete from actor where id =1";
        //statement:用于执行静态的sql语句并返回其生成的结果对象
        Statement statement = connect.createStatement();
        //如果是dml语句,返回的就是影响行数
        int rows = statement.executeUpdate(sql);
        System.out.println(rows);

        System.out.println(rows > 0 ? "成功" : "失败");

        //4.关闭连接资源
        statement.close();
        connect.close();
    

输出结果如下

成功

四、Java操作数据库需要获得Connection连接,获取Connection连接的五种方式如下

public class JdbcConn 
    //方式1
    @Test
    public void connect01() throws SQLException 
        //1.注册驱动
        Driver driver = new Driver();//创建Driver对象

        String url = "jdbc:mysql://localhost:3306/db_ly?serverTimezone=GMT";

        //将用户名和密码放入到Properties对象
        Properties properties = new Properties();
        //说明 user 和 password 是规定好的,后面的值根据实际情况写
        properties.setProperty("user", "root");//用户
        properties.setProperty("password", "123456");//密码

        Connection connect = driver.connect(url, properties);
        System.out.println(connect);
    

    //方式2
    @Test
    public void connect02() throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException 
        //使用反射获取Driver类,动态加载,更加的灵活,减少依赖性
        Class<?> aClass = Class.forName("com.mysql.cj.jdbc.Driver");
        Driver driver = (Driver) aClass.newInstance();
        String url = "jdbc:mysql://localhost:3306/db_ly?serverTimezone=GMT";

        //将用户名和密码放入到Properties对象
        Properties properties = new Properties();
        //说明 user 和 password 是规定好的,后面的值根据实际情况写
        properties.setProperty("user", "root");//用户
        properties.setProperty("password", "123456");//密码

        Connection connect = driver.connect(url, properties);
        System.out.println(connect);
    

    //方法3 使用DriverManager 替代driver 进行统一管理
    @Test
    public void connect03() throws IllegalAccessException, InstantiationException, ClassNotFoundException, SQLException 
        Class<?> aClass = Class.forName("com.mysql.cj.jdbc.Driver");
        Driver driver = (Driver) aClass.newInstance();

        //创建url和user的password
        String url = "jdbc:mysql://localhost:3306/db_ly?serverTimezone=GMT";
        String user = "root";
        String password = "123456";

        //注册driver驱动
        DriverManager.registerDriver(driver);
        Connection connection = DriverManager.getConnection(url, user, password);
        System.out.println("第三种方式:" + connection);
    

    //方式4:使用Class.forName() 自动完成注册驱动,简化代码
    //这种方式获取连接是使用的最多的,推荐使用
    @Test
    public void connect04() throws ClassNotFoundException, SQLException 
        //使用反射加载了Driver类
        //在加载Driver类时,完成注册
        /*
            源码:1.静态代码块,在类加载时,会执行一次
                 2. DriverManager.registerDriver(new Driver());
                 3.因此注册driver的工作已经完成
            static 
                try 
                    DriverManager.registerDriver(new Driver());
                 catch (SQLException var1) 
                    throw new RuntimeException("Can't register driver!");
                
            
         */
        Class.forName("com.mysql.cj.jdbc.Driver");
        //创建url和user的password
        String url = "jdbc:mysql://localhost:3306/db_ly?serverTimezone=GMT";
        String user = "root";
        String password = "123456";
        Connection connection = DriverManager.getConnection(url, user, password);
        System.out.println("第四种方式:" + connection);
    

    //方式5:在方式4的基础上改进,增加配置文件,让连接mysql更加灵活
    @Test
    public void connect05() throws IOException, ClassNotFoundException, SQLException 
        //通过Properties,获取相关配置文件的信息
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\\\mysql.properties"));
        //获取相关的值
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");
        String driver = properties.getProperty("driver");
        String url = properties.getProperty("url");

        Class.forName(driver);
        Connection connection = DriverManager.getConnection(url, user, password);
        System.out.println("第五种方式:" + connection);
    

输出结果

com.mysql.cj.jdbc.ConnectionImpl@1a38c59b
com.mysql.cj.jdbc.ConnectionImpl@1a38c59b
第三种方式:com.mysql.cj.jdbc.ConnectionImpl@7f77e91b
第四种方式:com.mysql.cj.jdbc.ConnectionImpl@1a38c59b
第五种方式:com.mysql.cj.jdbc.ConnectionImpl@1a38c59b

四、ResultSet的详解


对应的代码如下

@SuppressWarnings("all")
public class ResultSet_ 
    public static void main(String[] args) throws Exception 
        //通过Properties配置相关信息
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\\\mysql.properties"));
        //获取相关的值
        String url = properties.getProperty("url");
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");
        String driver = properties.getProperty("driver");
        //1.注册驱动
        Class.forName(driver);
        //建立与给定数据库的url连接
        //2.建立连接
        Connection connection = DriverManager.getConnection(url, user, password);

        //3.得到Statement
        Statement statement = connection.createStatement();
        //4.组织sql
        String sql = "SELECT id,name,sex,borndate,phone FROM ACTOR";

        //执行给定的SQL语句,该语句返回单个 ResultSet对象。
        /*

        +----+--------+-----+---------------------+-----------+
        | id | NAME   | sex | borndate            | phone     |
        +----+--------+-----+---------------------+-----------+
        |  1 | 刘德华 || 1970-01-01 00:00:00 | 110       |
        |  2 | 王宝强 || 1980-01-03 00:00:00 | 123456789 |
        +----+--------+-----+---------------------+-----------+
         */
        /*
            resultSet对象的结构,debug进行阅读

            查询到的数据,底层使用byte[] 数组存的,比如id =1  存放的1对应的ASCII码49
         */
        ResultSet resultSet = statement.executeQuery(sql);

        //5.使用while取出数据
        while (resultSet.next()) //让光标向后移动,如果没有更多行,则返回false
           // int id = resultSet.getInt(1);//获取该行的第一列数据
            int id = resultSet.getInt("id");//通过列名来获取值,推荐使用
            String name = resultSet.getString(2);//获取该行第二列
            String sex = resultSet.getString(3);//获取该行第三列
            Date date = resultSet.getDate(4);//获取该行第四列
            String phone = resultSet.getString(5);//获取该行第五列
            System.out.println(id + "\\t" + name + "\\t" + sex + "\\t" + date + "\\t" + phone);
        

        //6.关闭连接
        resultSet.close();
        statement.close();
        connection.close();
    


输出结果

1	刘德华	男	1970-01-01	110
2	王宝强	男	1980-01-03	123456789

resultSet对象的结构如下

Statement的介绍

使用Statement会存在SQL注入的风险,所以开发中一般使用PreparedStatement。

SQL注入演示:

CREATE TABLE ADMIN(
NAME VARCHAR(32) NOT NULL UNIQUE,
pwd VARCHAR(32) NOT NULL DEFAULT ''
);
INSERT INTO ADMIN VALUES('jack','123456');


SELECT * FROM ADMIN WHERE NAME='jack' AND pwd = '12456';

-- name 输入 1'or 
-- pwd 输入or '1'='1
-- 条件'1'='1' 永远成立 能查到数据库中的数据,JAVA程序在拼接的时候就发生了SQL注入
SELECT * FROM ADMIN 
WHERE NAME='1'or' AND pwd = 'or '1'='1';

下面演示使用Statement会发生SQL注入的风险

public class Statement_ 
    public static void main(String[] args) throws Exception 

        Scanner scanner = new Scanner(System.in);
        //让用户输入管理员名和密码
        System.out.println("请输入管理员的名字:");//next():当接收到空格或者 '就是表示结束
        String admin_name = scanner.nextLine();//如果希望看到SQL注入效果,这里需要nextLine() 这个回车才表示结束
        System.out.println("请输入管理员的密码:");
        String admin_pwd = scanner.nextLine();

        //通过Properties配置相关信息
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\\\mysql.properties"));
        //获取相关的值
        String url = properties.getProperty("url");
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");
        String driver = properties.getProperty("driver");
        //1.注册驱动
        Class.forName(driver);
        //建立与给定数据库的url连接
        //2.建立连接
        Connection connection = DriverManager.getConnection(url, user, password);

        //3.得到Statement
        Statement statement = connection.createStatement();
        //4.组织sql
        String sql = "SELECT NAME,pwd FROM ADMIN WHERE NAME='" + admin_name + "' AND pwd= '" + admin_pwd + "'";

        ResultSet resultSet = statement.executeQuery(sql);
        if (resultSet.next()) //如果查询到一条记录,则说明该管理存在
            System.out.println("恭喜登录成功!");
         else 
            System.out.println("登录失败!");
        

        //关闭连接
        resultSet.close();
        statement.close();
        connection.close();
    

输出结果如下

请输入管理员的名字:
1'or
请输入管理员的密码:
or '1'='1
恭喜登录成功!

五、PrepareStatement的介绍与使用

PrepareStatement的好处

1、下面是演示代码,解决了SQL注入的问题

public class PrepareStatement_ 
    public static void main(String[] args) throws Exception 
        Scanner scanner = new Scanner(System.in);
        //让用户输入管理员名和密码
        System.out.println("请输入管理员的名字:");//next():当接收到空格或者 '就是表示结束
        String admin_name = scanner.nextLine();//如果希望看到SQL注入效果,这里需要nextLine() 这个回车才表示结束
        System.out.println("请输入管理员的密码:");
        String admin_pwd = scanner.nextLine();

        //通过Properties配置相关信息
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\\\mysql.properties"));
        //获取相关的值
        String url = properties.getProperty("url");
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");
        String driver = properties.getProperty("driver");
        //1.注册驱动
        Class.forName(driver);
        //建立与给定数据库的url连接
        //2.建立连接
        Connection connection = DriverManager.getConnection(url, user, password);

        //3.组织sql语句,sql语句的? 就相当于占位符
        String sql = "SELECT name,pwd FROM ADMIN WHERE name=? AND pwd=?";
        //4.得到preparedStatement
        //preparedStatement对象是实现了PreparedStatement接口的实现类对象
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        //给?赋值
        preparedStatement.setString(1, admin_name);
        preparedStatement.setString(2, admin_pwd);

        //执行select语句,使用executeQuery()
        //如果执行的是dml(update,insert,delete) 使用executeUpdate()
        //这里执行executeQuery,不要写sql
        ResultSet resultSet = preparedStatement.executeQuery();
        if (resultSet.next()) //如果查询到一条记录,则说明该管理存在
            System.out.println("登录成功!");
         else 
            System.out.println("登录失败!");
        

        //关闭连接
        resultSet.close();
        preparedStatement.close();
        connection.close();
    

输出结果

请输入管理员的名字:
1 'or 
请输入管理员的密码:
or '1'='1
登录失败!

2、使用PrepareStatement进行DML操作

public class PrepareStatement_DML 
    public static void main(String[] args) throws Exception 
        Scanner scanner = new Scanner(System.in);
        //让用户输入管理员名和密码
        System.out.println("请输入要删除的管理员的名字:");//next():当接收到空格或者 '就是表示结束
        String admin_name = scanner.nextLine();//如果希望看到SQL注入效果,这里需要nextLine() 这个回车才表示结束
//        System.out.println("请输入管理员的密码:");
//        String admin_pwd = scanner.nextLine();

        //通过Properties配置相关信息
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\\\mysql.properties"));
        //获取相关的值
        String url = properties.getProperty("url");
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");
        String driver = properties.getProperty("driver");
        //1.注册驱动
        Class.forName(driver);
        //建立与给定数据库的url连接
        //2.建立连接
        Connection connection = DriverManager.getConnection(url, user, password);

        //3.组织sql语句,sql语句的? 就相当于占位符
        //添加记录
//        String sql = "insert into admin values(?,?)";

        //修改记录
//        String sql = "update admin set name=? where pwd=?";

        //删除记录
        String sql = "delete from admin where name=?";

        //4.得到preparedStatement
        //preparedStatement对象是实现了PreparedStatement接口的实现类对象
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        //给?赋值
        preparedStatement.setString(1, admin_name);
//        preparedStatement.setString(2, admin_pwd);

        //如果执行的是dml(update,insert,delete) 使用executeUpdate()
        int rows = preparedStatement.executeUpdate();
        System.out.println(rows > 0 ? "执行成功" : "执行失败");

        //关闭连接
        preparedStatement.close();
        connection.close();
    

输出结果

请输入要删除的管理员的名字:
smith
执行成功

以上是关于Java Jdbc的详解的主要内容,如果未能解决你的问题,请参考以下文章

SQL注入与jdbc操作详解

JDBC详解系列之加载驱动

(4)数据源datasource详解

JDBC连接数据

MySql JDBC url 参数详解

java:JDBC详解