JDBC初步

一.JDBC概述

一.什么是JDBC

Java DataBase Connectivity(Java语言连接数据库)
JDBC是SUN公司制定的一套接口(interface)
java.sql.*; (这个软件包下有很多接口。)

接口都有调用者和实现者。
面向接口调用、面向接口写实现类,这都属于面向接口编程。

为什么要面向接口编程?
	解耦合:降低程序的耦合度,提高程序的扩展力。
	多态机制就是非常典型的:面向抽象编程。(不要面向具体编程)
	为什么SUN制定一套JDBC接口呢?
	因为每一个数据库的底层实现原理都不一样。
	Oracle数据库有自己的原理。
	MySQL数据库也有自己的原理。
	MS SqlServer数据库也有自己的原理。
	....
	每一个数据库产品都有自己独特的实现原理。

JDBC的本质到底是什么?
	一套接口。
二.JDBC开发前的准备工作

先从官网下载对应的驱动jar包,然后将其配置到环境变量classpath当中。
以上的配置是针对于文本编辑器的方式开发,使用IDEA工具的时候,不需要配置以上的环境变量。IDEA有自己的配置方式。下面我来演示一下.
1.选择一个Module
在这里插入图片描述

2.点击 Open Module Settings
在这里插入图片描述
3.选择Libraries
在这里插入图片描述
4.点击加号,选择对应的jar包在这里插入图片描述

二.JDBC编程六步

第一步:注册驱动(作用:告诉Java程序,即将要连接的是哪个品牌的数据库)

第二步:获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,重量级的,使用完之后一定要关闭通道。)

第三步:获取数据库操作对象(专门执行sql语句的对象)

第四步:执行SQL语句(DQL DML....)

第五步:处理查询结果集(只有当第四步执行的是select语句的时候,才有这第五步处理查询结果集。)

第六步:释放资源(使用完资源之后一定要关闭资源。Java和数据库属于进程间的通信,开启之后一定要关闭。)

三.JDBC实践

实例一:
import java.sql.*;

/*
    JDBC编程六步
 */
public class JDBCTest01 {
    public static void main(String[] args) {
        Connection connection =null;
        Statement statement = null;
        try {
            // 1.获取驱动
            Driver driver = new com.mysql.jdbc.Driver();
            DriverManager.registerDriver(driver);
            // 2.建立连接
            String url = "jdbc:mysql://127.0.0.1:3306/testdatabase";
            String username = "root";
            String password = "123";
            connection = DriverManager.getConnection(url,username,password);
            // 3.获取数据库操作对象
            statement = connection.createStatement();
            // 4.执行SQL语句
            String sql = "insert into dept(deptno,dname,loc) values(50,'人事部','北京')";
            //专门执行DML语句(insert delete update)
            //返回值是"影响数据库中的记录的条数"
            int count = statement.executeUpdate(sql);
            System.out.println(count);   // 1
            // 5.处理查询结果集(只在select语句中才用)
            // 6.释放资源
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            if (statement != null){
                try {
                    statement.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }if (connection != null){
                try {
                    connection.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }

    }
}

实例二(一)

使用JDBC完成update和delete
代码执行前:
在这里插入图片描述
代码执行后:
在这里插入图片描述
代码部分:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBCTest02 {
    public static void main(String[] args) {
        Connection connection = null;
        Statement statement = null;
        try {
            // 1.注册驱动
            DriverManager.registerDriver(new com.mysql.jdbc.Driver());
            // 2.建立连接
            String url = "jdbc:mysql://localhost:3306/testdatabase";
            String username = "root";
            String password = "123";
            connection = DriverManager.getConnection(url,username,password);
            // 3.获取数据库操作对象
            statement= connection.createStatement();
            // 4.执行SQL语句
            String sql = "delete from dept where deptno = 40";
            int count = statement.executeUpdate(sql);
            System.out.println(count == 1? "删除成功":"删除失败");
            // 5.处理查询结果集
            // 6.关闭资源
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            if (statement != null){
                try {
                    statement.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }if (connection != null){
                try {
                    connection.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }

    }
}

在这里插入图片描述

实例二(一)

代码执行前:
在这里插入图片描述
代码执行后:
在这里插入图片描述

/*
    JDBC完成delete,update
 */

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBCTest02 {
    public static void main(String[] args) {
        Connection connection = null;
        Statement statement = null;
        try {
            // 1.注册驱动
            DriverManager.registerDriver(new com.mysql.jdbc.Driver());
            // 2.建立连接
            String url = "jdbc:mysql://localhost:3306/testdatabase";
            String username = "root";
            String password = "123";
            connection = DriverManager.getConnection(url,username,password);
            // 3.获取数据库操作对象
            statement= connection.createStatement();
            // 4.执行SQL语句
            // String sql = "delete from dept where deptno = 40";
            String sql = "update dept set dname = '销售部' ,loc = '苏州' where  deptno = 20";
            int count = statement.executeUpdate(sql);
            System.out.println(count == 1? "更新成功":"更新失败");
            // 5.处理查询结果集
            // 6.关闭资源
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            if (statement != null){
                try {
                    statement.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }if (connection != null){
                try {
                    connection.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }

    }
}

在这里插入图片描述

实例三
// 注册驱动的另一种方式
public class JDBCTest03 {
    public static void main(String[] args) {
        try {
            //这种注册方法更常用,用到了静态代码块的知识
            //静态代码块的类加载的时候执行,只执行一次
            //注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            //获取连接
            Connection connection = DriverManager.getConnection("jdbc:mysql//:localhost:3306/testdatabase");

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            // 关闭
        }
    }
}

实例四
// 将连接数据库的所有信息配置到配置文件中去
/*
    实际开发中不建议把数据连接到数据库中的信息写死到java程序中
 */
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collection;
import java.util.ResourceBundle;

public class JDBCTest04 {
    public static void main(String[] args) {

        //  使用资源绑定器绑定属性配置文件
        // java.util包下提供了一个资源绑定器,便于获取属性配置文件中的内容
        // 使用以下这种方式打包,属性配置文件xxx.properties必须放到类路径下
        // 资源绑定器,只能绑定xxx.properties文件,并且这个文件必须在类路径下,文件拓展名也必须是properties
        // 并且写路径的时候,后面的拓展名不写    .properties不写
        ResourceBundle bundle = ResourceBundle.getBundle("com/JDBC");
        String driver = bundle.getString("driver");
        String url = bundle.getString("url");
        String user = bundle.getString("user");
        String password = bundle.getString("password");

        Connection connection =null;
        Statement statement = null;
        try {
            //1.注册驱动
            Class.forName(driver);
            //2.获取连接
            connection = DriverManager.getConnection(url,user,password);
            //3.获取数据库连接对象
            statement = connection.createStatement();
            //4.执行SQL语句
            // String sql = "delete from dept where deptno = 40";
            //JDBC 的sql语句不要写分号
            String sql = "update dept set dname = '销售部2' ,loc = '苏州2' where  deptno = 20";
            int count = statement.executeUpdate(sql);
            System.out.println(count == 1 ? "修改成功" : "修改失败");
            //5.处理查询结果集(只有在select语句中才会用)
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (connection!= null){
                try {
                    connection.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (statement != null){
                try {
                    statement.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
    }
}

实例五:
import java.sql.*;

// 使用JDBC调用查询语句
public class JDBCTest05 {
    public static void main(String[] args) {
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        try {// 1.注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 2.获取连接
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/testdatabase","root","123");
            // 3.获取数据库操作对象
            statement = connection.createStatement();
            // 4.执行sql语句
            String sql = "select empno,ename,sal from emp";
            resultSet = statement.executeQuery(sql);
            // 5.处理查询数据集
            while(resultSet.next()){
                // 这样是通过列的下标获取的, getString 可以将得到的信息全部变为String类型
                /*String empno = resultSet.getString(1);
                String ename = resultSet.getString(2);
                String sal = resultSet.getString(3);*/
                String empno = resultSet.getString("empno");
                String ename = resultSet.getString("ename");
                //String sal = resultSet.getString("sal");
                // 还可以直接按着int 类型提出来
                int sal = resultSet.getInt("sal");
                System.out.println(empno + " , " + ename + " , " +sal);
            }
            // 6.关闭资源

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            if (resultSet != null){
                try {
                    resultSet.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }if (statement != null){
                    try {
                        statement.close();
                    } catch (SQLException throwables) {
                        throwables.printStackTrace();
                    }
                }if (connection != null){
                    try {
                        connection.close();
                    } catch (SQLException throwables) {
                        throwables.printStackTrace();
                    }
                }
            }
        }
    }
}

在这里插入图片描述

实例六(一):实现用户的登陆
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

/*
实现功能:
    1.需求:模拟用户登录功能的实现
    2.业务需求:
        程序运行的时候,提供一个输入的入口,可以让用户输入用户名的密码
        用户输入用户名和密码之后,提交信息,java程序收集到用户信息
        java程序连接数据库验证用户名和密码是否合法
        合法:显示登陆成功
        不合法:显示登陆失败
    3.数据的准备:
        在实际开发中,表的设计会使用一个专业的建模工具,我们这里安装一个建模工具:powerDesigner
        使用PD工具来进行数据库表的设计(参见user-login.sql脚本)
    4.当前程序存在的问题:
        请输入用户名:
        dashuaige
        请输入密码
        dashuaige ' or '1' = '1
        登陆成功
        这种现象叫做sql注入(安全隐患)
    5.导致SQL注入的根本原因是什么?
        用户输入的信息中含有sql语句的关键字,并且这些关键字参与sql语句的编译过程
        导致sql语句的原意被扭曲,进而达到了sql注入.
*/
public class JDBCTest06 {
    public static void main(String[] args) {
        // 初始化一个界面
        Map<String,String> userLoginInfo = initUI();
        // 验证用户名和密码
        boolean loginSuccess = login(userLoginInfo);
        // 输出结果
        System.out.println(loginSuccess ? "登陆成功" : "登录失败");
    }

    /**
     * 用户登陆
     * @param userLoginInfo    用户登陆信息
     * @return  false 表示失败 true 表示成功
     */
    private static boolean login(Map<String, String> userLoginInfo) {
        //打标记意识
        boolean loginFlag = false;
        //单独定义变量
        String loginName = userLoginInfo.get("LoginName");
        String loginPwd = userLoginInfo.get("LoginPwd");
        //JDBC 代码
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        try {
            // 1.注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 2.获取连接
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/testdatabase","root","123");
            // 3.获取数据库操作对象
            statement = connection.createStatement();
            // 4.执行sql
            String sql = "select * from t_user where loginName = '"+ loginName +"' and loginPwd = '"+ loginPwd+"'" ;
            //以上正好完成了sql语句的拼接,以下代码的含义是,发送SQL语句到DBMS,DBMS进行sql编译.
            //真好将用户提供的"非法信息"编译进去,导致原sql语句的含义被扭曲了
            resultSet = statement.executeQuery(sql);
            // 5.处理结果集
            if(resultSet.next()){
                // 登陆成功
                loginFlag = true;
            }
            // 6.释放资源
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }if (statement != null){
            try {
                statement.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }if (connection != null){
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        return loginFlag;
    }

    /**
     *  初始化用户界面
     * @return 用户输入的用户名和密码等登录信息
     */
    private static Map<String, String> initUI() {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String LoginName = scanner.nextLine();
        System.out.println("请输入密码");
        String LoginPwd = scanner.nextLine();

        Map<String,String> userLoginInfo = new HashMap<>();
        userLoginInfo.put("LoginName",LoginName);
        userLoginInfo.put("LoginPwd",LoginPwd);

        return userLoginInfo;
    }
}

实验六(二):解决SQL注入
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

/*
* 1.如何解决sql注入的问题?
*   主要用户提供的信息不参与SQL语句的编译过程,问题就解决了
*   即使用户提供的信息中含有sql语句的关键字,但是没有参与编译,不起作用
*   要想用户的信息不参与SQL语句的编译,那么必须使用java.sql.PreparedStatement
*   PreparedStatement属于预编译的数据库操作对象
*   PreparedStatement原理是:预先对SQL语句的框架进行编译,然后再给SQL语句传"值".
* 2.//解决了sql注入的问题
        //请输入用户名:
        //dashuaige
        //请输入密码
        //dashuaige ' or '1' = '1
        //登录失败
  3.解决SQL注入的关键是:用户提供的信息中即使含有SQL语句的关键字,但是这些关键字并没有参与编译,不起作用
  4.对比Statement和PreparedStatement?
  -  Statement存在SQL注入的问题, PreparedStatement解决了SQL注入的问题
  -  Statement是编译一次执行一次, PreparedStatement 是编译一次执行n次    PreparedStatement 效率更高
  -  PreparedStatement 会在编译阶段做类型的安全检查
  *
  * 综上所述: PreparedStatement 使用较多,只有极少数情况下需要使用Statement
  5. 什么情况下必须使用SQL注入?
  *     业务方面要求必须使用SQL注入的时候
  *     Statement支持SQL注入,凡是业务方面是需要SQL语句拼接的,必须使用Statement
* */
public class JDBCTest07 {
    public static void main(String[] args) {
        // 初始化一个界面
        Map<String,String> userLoginInfo = initUI();
        // 验证用户名和密码
        boolean loginSuccess = login(userLoginInfo);
        // 输出结果
        System.out.println(loginSuccess ? "登陆成功" : "登录失败");
    }

    /**
     * 用户登陆
     * @param userLoginInfo    用户登陆信息
     * @return  false 表示失败 true 表示成功
     */
    private static boolean login(Map<String, String> userLoginInfo) {
        //打标机意识
        boolean loginFlag = false;
        //单独定义变量
        String loginName = userLoginInfo.get("LoginName");
        String loginPwd = userLoginInfo.get("LoginPwd");
        //JDBC 代码
        Connection connection = null;
        //Statement statement = null;
        PreparedStatement preparedStatement =null;
        ResultSet resultSet = null;
        try {
            // 1.注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 2.获取连接
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/testdatabase","root","123");
            // 3.获取数据库操作对象
            // statement = connection.createStatement();
            // 3.获取预编译的数据库操作对象
            // 问号里面只能添加值,一个问号代表一个占位符,一个问号将来接受一个值,注意:占位符不能用单引号括起来
            String sql = "select * from t_user where loginName = ? and loginPwd = ?" ;      //sql语句的框子
            //程序执行到此,会发送sql语句的框子到DBMS,然后DBMS会进行sql语句的预先编译
            preparedStatement = connection.prepareStatement(sql);
            //给占位符?传值(第一个问号下表是1,第二个问号下标是2,JDBC所有的下标从1开始)
            preparedStatement.setString(1,loginName);
            preparedStatement.setString(2,loginPwd);
            // 4.执行sql
            //String sql = "select * from t_user where loginName = '"+ loginName +"' and loginPwd = '"+ loginPwd+"'" ;
            //resultSet = statement.executeQuery(sql);
            resultSet = preparedStatement.executeQuery();
            // 5.处理结果集
            if(resultSet.next()){
                // 登陆成功
                loginFlag = true;
            }
            // 6.释放资源
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }if (preparedStatement != null){
            try {
                preparedStatement.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }if (connection != null){
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        return loginFlag;
    }
    /**
     *  初始化用户界面
     * @return 用户输入的用户名和密码等登录信息
     */
    private static Map<String, String> initUI() {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String LoginName = scanner.nextLine();
        System.out.println("请输入密码");
        String LoginPwd = scanner.nextLine();

        Map<String,String> userLoginInfo = new HashMap<>();
        userLoginInfo.put("LoginName",LoginName);
        userLoginInfo.put("LoginPwd",LoginPwd);

        return userLoginInfo;
    }
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值