java 操作数据库之JDBC基础知识温习

什么是JDBC?

  • JDBC是(java database connectivity),是sun公司采用java语言编写的链接数据库的标准规则接口。

JDBC能帮我们做什么?

  • jdbc使用统一的一套java代码可以实现操作所有关系型数据库。其接口操作如下所示:
    在这里插入图片描述
  • sun公司提供统一的数据库驱动接口,各大数据库厂商根据sun公司提供的接口来编写自己的实现类,并封装成jar包,此类jar包也就成了各大厂商的数据库驱动了,当我们需要使用某种数据库时,只需要将数据库对应的jar包导入进来即可正常连接数据库。(真正执行的代码是驱动jar包中的实现类)。

JDBC 如何使用?

使用步骤:

1.导入驱动jar包

手动导入

  1. 复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下
  2. 右键–>Add As Library
    在这里插入图片描述

maven 依赖导入

注册驱动步骤

1、 获取数据库连接对象connection
2、 定义sql
3、 获取sql 语句的对象statement
4、 执行sql,接收返回结果
5、 处理结果
7、 释放资源

java操作数据库案例

public class JdbcTest {
    public static void main(String[] args) throws ClassNotFoundException {
        Connection connection = null;
        Statement statement = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            /*connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test2",
            "root","root");*/
             connection = DriverManager.getConnection("jdbc:mysql:///test2",
                    "root", "root");
            statement = connection.createStatement();

            String  sql = "update account set balance = 1000; -- where id =1;";
            int i = statement.executeUpdate(sql);
            if(i<1){
                System.out.println("执行失败!!!");
            }else{
                System.out.println(i);
                System.out.println("执行成功!!!");
            }

        } 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中常用的对象

DriverManager 驱动管理对象

DriverManager管理对象都做了什么事情?
其实DriverManager 所做的事情主要是由以下两部分组成。

1、注册驱动

注册驱动其实是告诉系统是在使用哪一个数据库驱动jar包。
在DriverManager 中有一个静态函数:

public static void registerDriver(Driver driver)
                           throws SQLException

但写代码却发现直接使用Class.forName来加载驱动

Class.forName("com.mysql.jdbc.Driver");

这两者有什么关系呢?
其实秘密在于com.mysql.jdbc.Driver的源码中,源码中有静态方法,当用class.forName(“xxx”)加载文件时,com.mysql.jdbc.Driver的静态代码块自动执行,静态代码块中的注册驱动的代码就会自动执行了,其部分源码如下所示:

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    public Driver() throws SQLException {
    }

    static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }
}

notes:在mysql-connector-java 5.0版本之后,Class.forName(“xxx”)这个语句就可以省略了。因为在5.0后加入了配置文件,当程序加载会自动读取配置文件里面的内容,因此上述步骤可以省略。
在这里插入图片描述

2、获取数据库连接

获取代码方式:

  static Connection getConnection(String url, String user, String password)
 

参数

  • url : 指定连接的路径
    语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
    例子:jdbc:mysql://localhost:3306/test1
    细节:如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称
    user: 用户名
    password: 密码

Connection 数据库连接对象

功能
  1. 获取数据库连接:
 Statement  createStatement();
 PrepareStatement  prepareStatement(String sql);
  1. 管理事务
  • 开启事务: setAutoCommit(boolean autoCommit):调用方法为false即为开启事务。
  • 提交事务 commit();
  • 回滚事务 rollback();

Statement 执行sql的对象

用于执行静态SQL语句并返回其生成的结果的对象。

boolean execute(String sql) throws SQLException

上述sql可以执行任何sql;

int executeUpdate(String sql) throws SQLException

一般情况下,该sql执行DML(insert, update, delete)语句、DDL(data definition language)(create,alter,drop)语句
返回值,表示印象的行数,可以通过这个影响的行数判断DML语句是否执行成功 返回值>0的则执行成功,反之,则失败。

ResultSet executeQuery(String sql)  :执行DQL(select)语句

ResultSet: 结果集对象

本身是用于封装查询后的结果。
getXxx():获取数据。
Xxx:代表数据类型 如 int getInt(),String getString();
参数:

  • int: 代表列的编号,从1开始,如: getString();
    String :代表列名称。如: getDouble(“balance”)
案例一
public class Jdbc02Test {
    public static void main(String[] args) {
        List<Emp> all = findAll();
        for (Emp emp :
                all) {
            System.out.println(emp);
        }
    }
    public static List<Emp> findAll(){
        Connection connection =null;
        Statement statement = null;
        ResultSet resultSet = null;
        LinkedList<Emp> emps =null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql:///test2",
                    "root", "root");
            statement = connection.createStatement();
            String sql = "select * from account;";
            resultSet = statement.executeQuery(sql);

            /*while (resultSet.next()){
                int anInt = resultSet.getInt(1);
                String name = resultSet.getString("name");
                double balance = resultSet.getDouble("balance");
                System.out.println(anInt+"----->"+name+"----->"+balance);
            }*/
             emps = new LinkedList<>();

            while (resultSet.next()){
                Emp emp = new Emp();
                emp.setId(resultSet.getInt(1));
                emp.setName(resultSet.getString("name"));
                emp.setBalance(resultSet.getDouble("balance"));
                emps.add(emp);
            }

        } catch (ClassNotFoundException | SQLException e) {
            e.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();
                }
            }
        }
        return emps;
    }
}

查询结果:
在这里插入图片描述

案例二

采用list形式将查询的结果打印出来
实体类:

public class Emp {
    private  int id;
    private  String name;
    private  Double balance;
    public Emp() {
    }
    public Emp(int id, String name, Double balance) {
        this.id = id;
        this.name = name;
        this.balance = balance;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getBalance() {
        return balance;
    }

    public void setBalance(Double balance) {
        this.balance = balance;
    }
    @Override
    public String toString() {
        return "Emp{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", balance=" + balance +
                '}';
    }
}

测试类:

public class JdbcTest {
    public static void main(String[] args) throws ClassNotFoundException {
        Connection connection = null;
        Statement statement = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            /*connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test2",
            "root","root");*/
             connection = DriverManager.getConnection("jdbc:mysql:///test2",
                    "root", "root");
            statement = connection.createStatement();
            String  sql = "update account set balance = 1000; -- where id =1;";

            int i = statement.executeUpdate(sql);
            if(i<1){
                System.out.println("执行失败!!!");
            }else{
                System.out.println(i);
                System.out.println("执行成功!!!");
            }

        } 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();
                }
            }
        }
    }
}

在这里插入图片描述

PreparedStatement

SQL注入问题:
  • 在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题,如JDBCUtils中的案例二中就发生了sql注入现象
  1. 输入用户随便,输入密码:a’ or ‘a’ = 'a
  2. 在实际数据库中所执行的sql如下所示
select 
	* 
from 
	account 
where 
	username = 'woailuo' 
and 
	password= 'wo' 
or 
	'ailuo' = 'ailuo';
如何解决sql注入问题

sun公司提供了PreparedStatement对象来解决sql注入的问题。

预编译的SQL

参数使用?作为占位符

抽取JDBCUtils 类

案例一

将加载资源文件和释放资源文件抽象成一个工具类,然后实现数据库操作

资源文件

url=jdbc:mysql:///test2
username=root
password=root
driver=com.mysql.jdbc.Driver

实体类

public class Emp {
    private  int id;
    private  String name;
    private  Double balance;
    public Emp() {
    }
    public Emp(int id, String name, Double balance) {
        this.id = id;
        this.name = name;
        this.balance = balance;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getBalance() {
        return balance;
    }

    public void setBalance(Double balance) {
        this.balance = balance;
    }
    @Override
    public String toString() {
        return "Emp{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", balance=" + balance +
                '}';
    }
}

工具类

public class JDBCUtils {
    private  static  String url;
    private  static  String username;
    private  static  String password;
    private  static  String driver;
    //静态代码块,加载资源文件
    static {
        try {
            Properties properties = new Properties();
            //加载文件
            ClassLoader classLoader = JDBCUtils.class.getClassLoader();
            URL resource = classLoader.getResource("jdbc.properties");
            String path = resource.getPath();
            System.out.println(path);
            properties.load(new FileReader(path));
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");
            driver = properties.getProperty("driver");
            Class.forName(driver);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static  Connection  getConnection(){
        Connection connection = null;
        try {
             connection = DriverManager.getConnection(url, username, password);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            return connection;
        }
    }

    public static void close(Statement statement, Connection connection){
        if(statement != null){
            try {
                statement.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(connection != null){
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

    public static void close(ResultSet resultSet, Statement statement, Connection connection){
        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();
            }
        }
    }
}

测试类

Connection connection =null;
        Statement statement = null;
        ResultSet resultSet = null;
        LinkedList<Emp> emps =null;
        try {
             connection = JDBCUtils.getConnection();
            String sql = "select * from account;";
            statement = connection.createStatement();
            resultSet = statement.executeQuery(sql);
             emps = new LinkedList<>();
            while (resultSet.next()){
                Emp emp = new Emp();
                emp.setId(resultSet.getInt(1));
                emp.setName(resultSet.getString("name"));
                emp.setBalance(resultSet.getDouble("balance"));
                emps.add(emp);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(resultSet,statement,connection);
            return emps;
        }

测试结果
在这里插入图片描述

案例二

演示代码:
工具类、资源文件都与案例一保持一致,案例二无需实体类,需要稍微修改一下数据表。
需要修改数据库。

use test2;

alter TABLE account  add PASSWORD VARCHAR(20);

ALTER TABLE account CHANGE PASSWORD password VARCHAR(20);

ALTER TABLE account CHANGE NAME username VARCHAR(20);

UPDATE account SET PASSWORD = 'zhangsan' WHERE `NAME`='zhangsan'; 
UPDATE account SET PASSWORD = 'lisi' WHERE `NAME`='lisi'; 
SELECT * FROM account;
desc account;

数据库表和表结构如下所示:

在这里插入图片描述在这里插入图片描述
测试类:

public class jdbc03Test {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String username = scanner.nextLine();
        System.out.println("请输入密码:");
        String password = scanner.nextLine();
        boolean flag = login(username, password);
        if(flag){
            System.out.println("登录成功!!!");
        }else {
            System.out.println("登录失败!!!");
        }

    }
    public static boolean login(String username, String password){
        Connection connection =null;
        Statement statement = null;
        ResultSet resultSet = null;
        boolean loginFlag = false;
        try {
            connection = JDBCUtils.getConnection();
            String sql = "select * from account where username = '"+username+"' and password= '"+password+"';";
            System.out.println(sql);
            statement = connection.createStatement();
            resultSet = statement.executeQuery(sql);

            if(resultSet.next()){
                loginFlag = true;
                System.out.println(resultSet.getString(2));
                return  loginFlag;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(resultSet,statement,connection);
        }
        return loginFlag;
    }
}

演示sql 注入问题。
当随便输入账号:woailuo 密码:wo’ or ‘ailuo’ = 'ailuo
我们发现竟然成功的登录了。
在这里插入图片描述
可见sql注入问题还是比较严重。
我们已经知晓PreparedStatement可以解决sql注入问题,下面的案例三将展示如何使用PreparedStatement对象。

案例三

资源类,工具类保持与案例二一致,改动statement对象为preparestatement

public class JDBC04Test {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String username = scanner.nextLine();
        System.out.println("请输入密码:");
        String password = scanner.nextLine();
        boolean flag = login(username, password);
        if(flag){
            System.out.println("登录成功!!!");
        }else {
            System.out.println("登录失败!!!");
        }
    }
    public static boolean login(String username,String password){
        if(username == null || password==null){
            return false;
        }
        Connection connection =null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        boolean loginFlag = false;
        try {
            connection = JDBCUtils.getConnection();
            String sql = "select * from account where username = ? and password= ?;";
            System.out.println(sql);
            preparedStatement = connection.prepareStatement(sql);
            //需要给问好赋值
            preparedStatement.setString(1,username);
            preparedStatement.setString(2,password);
            resultSet = preparedStatement.executeQuery();

            if(resultSet.next()){
                loginFlag = true;
                System.out.println(resultSet.getString(2));
                return  loginFlag;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(resultSet,preparedStatement,connection);
        }
        return loginFlag;
    }
}

在这里插入图片描述
sql注入失败,此问题得到解决。

jdbc事务控制

jdbc 事务控制过程

事务控制可以采用Connection对象。
开启事务:

  • setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务在执行sql之前开启事务:

提交事务:

  • commit(); 同一事务中所有sql执行完成后则提交事务。

回滚事务:

  • rollback(); 在catch中回滚事务

也可以来实现事务管理

案例一

本案例中工具类,资源类与抽取JDBCUtils 类保持一致

测试类

public class JDBC05Test {
    public static void main(String[] args) {
        System.out.println("----------交易开始前----------");
        List<Emp> all = findAll();
        for (Emp emp :
                all) {
            System.out.println(emp);
        }
        transaction("zhangsan","lisi",500);
        System.out.println("------交易完成后-------");
        all=findAll();
        for (Emp emp :
                all) {
            System.out.println(emp);
        }
    }

    public static boolean transaction(String user1, String user2, double val ){
        Connection connection =null;
        PreparedStatement preparedStatement1 = null, preparedStatement2=null;
        ResultSet resultSet = null;
        try {
            connection = JDBCUtils.getConnection();
            connection.setAutoCommit(false);
            String sql1 = " update account set balance = balance - ? where username = ?";
            String sql2 = " update account set balance = balance + ? where username = ?";
            preparedStatement1 = connection.prepareStatement(sql1);
            preparedStatement2 = connection.prepareStatement(sql2);
            preparedStatement1.setDouble(1,val);
            preparedStatement1.setString(2,user1);
            preparedStatement2.setDouble(1,val);
            preparedStatement2.setString(2,user2);

            int i = preparedStatement1.executeUpdate();
           // int i2= 4/0;
            int i1 = preparedStatement2.executeUpdate();
            connection.commit();

        } catch (Exception e) {
            try {
                if(connection !=null){
                    connection.rollback();
                }
            } catch (SQLException sqlException) {
                sqlException.printStackTrace();
            }
            e.printStackTrace();
            return false;
        }finally {
            JDBCUtils.close(resultSet,preparedStatement1,connection);
            JDBCUtils.close(resultSet,preparedStatement2,connection);
        }
        return  true;
    }
    
    public static List<Emp> findAll(){
        Connection connection =null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        LinkedList<Emp> emps =null;
        try {
            connection = JDBCUtils.getConnection();
            String sql = "select * from account;";
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();
            emps = new LinkedList<>();
            while (resultSet.next()){
                Emp emp = new Emp();
                emp.setId(resultSet.getInt(1));
                emp.setUsername(resultSet.getString("username"));
                emp.setBalance(resultSet.getDouble("balance"));
                emp.setPassword("password");
                emps.add(emp);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(resultSet,preparedStatement,connection);
            return emps;
        }
    }
}

当事务中没有异常时刻即整个事务正常运行
在这里插入图片描述
当事务中存在异常则直接回滚事务。

public class JDBC05Test {
    public static void main(String[] args) {
        System.out.println("----------交易开始前----------");
        List<Emp> all = findAll();
        for (Emp emp :
                all) {
            System.out.println(emp);
        }
        transaction("zhangsan","lisi",500);
        System.out.println("------交易完成后-------");
        all=findAll();
        for (Emp emp :
                all) {
            System.out.println(emp);
        }
    }

    public static boolean transaction(String user1, String user2, double val ){
        Connection connection =null;
        PreparedStatement preparedStatement1 = null, preparedStatement2=null;
        ResultSet resultSet = null;
        try {
            connection = JDBCUtils.getConnection();
            connection.setAutoCommit(false);
            String sql1 = " update account set balance = balance - ? where username = ?";
            String sql2 = " update account set balance = balance + ? where username = ?";
            preparedStatement1 = connection.prepareStatement(sql1);
            preparedStatement2 = connection.prepareStatement(sql2);
            preparedStatement1.setDouble(1,val);
            preparedStatement1.setString(2,user1);
            preparedStatement2.setDouble(1,val);
            preparedStatement2.setString(2,user2);

            int i = preparedStatement1.executeUpdate();
            int i2= 4/0;
            int i1 = preparedStatement2.executeUpdate();
            connection.commit();

        } catch (Exception e) {
            try {
                if(connection !=null){
                    connection.rollback();
                }
            } catch (SQLException sqlException) {
                sqlException.printStackTrace();
            }
            e.printStackTrace();
            return false;
        }finally {
            JDBCUtils.close(resultSet,preparedStatement1,connection);
            JDBCUtils.close(resultSet,preparedStatement2,connection);
        }
        return  true;
    }

    public static List<Emp> findAll(){
        Connection connection =null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        LinkedList<Emp> emps =null;
        try {
            connection = JDBCUtils.getConnection();
            String sql = "select * from account;";
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();
            emps = new LinkedList<>();
            while (resultSet.next()){
                Emp emp = new Emp();
                emp.setId(resultSet.getInt(1));
                emp.setUsername(resultSet.getString("username"));
                emp.setBalance(resultSet.getDouble("balance"));
                emp.setPassword("password");
                emps.add(emp);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(resultSet,preparedStatement,connection);
            return emps;
        }
    }
}

在这里插入图片描述
至此jdbc的基本知识就复习到这里。

猜你喜欢

转载自blog.csdn.net/xueshanfeitian/article/details/109086494
今日推荐