JavaWeb:jdbc(详细讲解)

1、jdbc简介

什么是jdbc

  • Java Data Base Connectivity:java数据库连接

jdbc作用

  • 通过jdbc可以让java程序操作数据库

jdbc的本质

  • 官方定义的一套操作所有关系型数据库的规则,即接口(API)
  • 各个数据库厂商去实现这个接口,提供数据库驱动jar包
  • 我们可以使用这套接口编程,真正执行的代码时驱动jar包中的实现类

jdbc的好处

  1. 我们只需要会调用jdbc接口中的方法即可,使用简单
  2. 使用同一套java代码,进行少量的修改就可以访问其他jdbc支持的数据库了
2、jdbc API介绍

jdbc四个核心对象

对象 说明
DriverManager 用于注册驱动
Connection 表示数据库的连接
Statement 执行SQL语句对象
ResultSet 结果集或一张虚拟表

jdbc使用步骤

  1. 注册驱动
  2. 获取数据库连接
  3. 获取执行SQL语句对象
  4. 执行SQL语句并返回结果
  5. 处理结果
  6. 释放资源
3、jdbc注册驱动

在使用jdbc之前我们需要导入jar包

image-20231030164453007

注册驱动API

java.sql.DriverManager类用于注册驱动,提供如下方法注册驱动

static void registerDriver(Driver driver)DriverManager注册给定驱动

代码示例:

    public static void main(String[] args) throws SQLException {
    
    
        //1、注册驱动
        DriverManager.registerDriver(new com.mysql.jdbc.Driver());
    }

注意:

  1. MySQL5之后的驱动包,可以省略注册驱动的步骤
  2. 自动加载jar包中META-INF/services/java.sql.Dreiver文件中的驱动类

4、Connection连接

Connection介绍

表示Java程序与数据库之间的连接,只有拿到Connection才能操作数据库

DriverManager类中的静态方法 描述
static Connection getConnection(String url, String user, String password) 连接到给定数据库URL,并返回连接

参数说明:

  1. String url:连接数据库的url,用于说明连接数据库的位置
  2. String user:数据库的账号
  3. String password:数据库的密码

连接数据库的URL地址格式:协议名:子协议://服务器名或IP地址:端口号/数据库名

以MySQL来写:

/**
* 1、协议名:jdbc
* 2、子协议:mysql
* 3、服务器名(本地):localhost
* 4、端口号:3306
* 5、数据库名:db1
**/
jdbc:mysql://localhost:3306/db1

获取Connection对象

public class Main {
    
    
    public static void main(String[] args) throws SQLException {
    
    
        //1、注册驱动
        DriverManager.registerDriver(new com.mysql.jdbc.Driver());

        //2、获取数据库连接
        Connection cn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1?useSSL=false", "root", "123456");
    }
}
5、Statement对象

获取Statement对象

在java.sql.Connection接口有如下方法获取到Statement对象

Statement createStatement()
创建一个Statement对象来将SQL语句发送到数据库

案例代码

public class Main {
    
    
    public static void main(String[] args) throws SQLException {
    
    
        //1、注册驱动
        DriverManager.registerDriver(new com.mysql.jdbc.Driver());

        //2、获取数据库连接
        Connection cn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1?useSSL=false", "root", "123456");

        //3、获取运送SQL的对象
        Statement state = cn.createStatement();
    }
}
6、JDBC实现对单表数据增删改操作

准备数据

CREATE TABLE USER (
  id INT AUTO_INCREMENT PRIMARY KEY,
  NAME VARCHAR(50),
  PASSWORD VARCHAR(50)
);

INSERT  INTO `user` VALUES
(NULL,'admin','123'),
(NULL,'test','123'),
(NULL,'gm','123');

CREATE DATABASE day17;

INSERT INTO USER VALUES(NULL,'weipeng','123');
6.1、使用Statement对象来执行SQL语句

API介绍

API 说明
ResultSet executeQuery(String sql) 用于执行查询语句,返回查询到的结果集合
int executeUpdate(String sql) 用于执行除查询外的SQL;返回影响的行数

代码案例:

public class demo01 {
    
    
    public static void main(String[] args) throws SQLException {
    
    
        /**
         * 1、注册驱动
         * 2、获取Connection连接
         * 3、执行Statement
         * 4、执行sql语句
         * 5、处理结果
         * 6、释放资源
         */
        //1、注册驱动
        DriverManager.registerDriver(new Driver());
        //2、获取Connection连接
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo?useSSL=false", "root", "123456");
        //执行Statement
        Statement statement = connection.createStatement();
        //定义sql语句
        String sql = "INSERT INTO USER VALUES(NUll,'xiao ','123');";
        //4、执行sql语句,返回影响函数
        int row = statement.executeUpdate(sql);
        System.out.println(row);

        //5、关闭资源
        statement.close();
        connection.close();
    }

}
6.2、ResultSet查询数据库

ResultSet原理

ResultSet用于保存执行查询SQL语句的结果,我们不能一次性取出所有的数据,需要一行一行的取出。

ResultSet内部有一个指针,记录获取到哪行数据

获取查询结果

  • boolean next() 将光标从当前位置向前移动一行,判断当前行是否有效

    • 返回值

      true :有效行,当前行有数据

      false:无效行,当前行没有数据

    • get(参数):获取数据

      数据类型:如 int getInt(参数);String getString(参数)

    • 参数: String 列的名称

案例代码

public class demo02 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        // 1、注册驱动
        DriverManager.registerDriver(new Driver());

        // 2、创建连接
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo?useSSL=false"
                , "root", "123456");

        // 3、获取Statement对象
        Statement statement = connection.createStatement();

        //编写SQL语句
        String sql = "select * from user;";

        //执行sql
        ResultSet resultSet = statement.executeQuery(sql);
        //循环输出结果集合
        while (resultSet.next()){
    
    
            int id = resultSet.getInt("id");
            String name = resultSet.getString("name");
            String password = resultSet.getString("password");

            System.out.println("id="+ id + ",name=" + name + ",password="+ password);
        }

        //关闭资源
        resultSet.close();
        statement.close();
        connection.close();
    }
}
6.3、查询结果封装对象

对象关系映射介绍

  • 表 ----> 类
  • 字段 ----> 成员变量
  • 一条记录 ----> 一个对象

案例

  • 先创建一个与数据库一一对应的实体类
  • 再查询数据并进行封装

案例代码

  • 实体类(字段要与mysql表一一对应,自行添加构造方法)
public class user {
    
    
    private int id;
    private String name;
    private String password;
}
  • 测试类
public class demo03 {
    
    
    public static void main(String[] args) throws SQLException {
    
    
        //1、注册驱动
        DriverManager.registerDriver(new Driver());

        //2、创建连接
        Connection connection = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/demo?useSSL=false", "root", "123456");

        //3、获取Statement对象
        Statement statement = connection.createStatement();

        //4、编写SQL语句
        String sql = "select * from user;";

        //5、执行SQL
        ResultSet resultSet = statement.executeQuery(sql);

        //6、创建集合
        ArrayList<user> list = new ArrayList<>();

        //7、循环遍历结果
        while (resultSet.next()){
    
    
            int id = resultSet.getInt("id");
            String name = resultSet.getString("name");
            String password = resultSet.getString("password");
            user newUser = new user(id, name, password);
            list.add(newUser);
        }

        //8、遍历集合
        for (user user : list) {
    
    
            System.out.println(user);
        }

        //9、关闭资源
        resultSet.close();
        statement.close();
        connection.close();
    }
}

7、JDBC中使用事务

数据准备

create table account(
    id int primary key auto_increment,
    name varchar(10),
    balance double
);

insert into account(name, balance) values ('张三',1000),('李四',1000);

JDBC事务API

Connection接口中与事务有关的方法

方法名 说明
void setAutoCommit(boolean autoCommit) false:开始事务,true:关闭事务
void commit() 提交事务
void rollback 回滚事务

使用步骤:

  1. 注册驱动
  2. 获取连接
  3. 开启事务
  4. 获取到Statement
  5. Statement执行SQL
  6. 提交或回滚事务
  7. 关闭资源

案例代码

public class demo04 {
    
    
    public static void main(String[] args) {
    
    
        Connection connection = null;
        Statement statement = null;
        try {
    
    
            //1、注册驱动
            DriverManager.registerDriver(new Driver());
            //2、获取连接
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo?useSSL=false",
                    "root", "123456");

            //3、开启事务
            connection.setAutoCommit(false);

            //4、获取到Statement
            statement = connection.createStatement();
            //5、执行sql,张三借给李四500
            statement.executeUpdate("update account set balance = balance - 500 where name = '张三'");
            statement.executeUpdate("update account set balance = balance + 500 where name = '李四'");

            //6、提交事务
            connection.commit();
            System.out.println("执行成功");
        } catch (Exception e) {
    
    

            try {
    
    
                //失败回滚事务
                if (connection != null){
    
    
                    connection.rollback();
                }
                System.out.println("执行失败");
            } catch (SQLException ex) {
    
    
                throw new RuntimeException(ex);
            }

        } finally {
    
    
            //关闭资源
            try {
    
    
                if (statement != null){
    
    
                    statement.close();
                }
            } catch (Exception e) {
    
    
                throw new RuntimeException(e);
            }

            try {
    
    
                if (connection != null){
    
    
                    connection.close();
                }
            } catch (SQLException e) {
    
    
                throw new RuntimeException(e);
            }

        }

    }

8、JDBC编写登录案例

用户输入账号和密码,有则登录成功,没有则失败

public class demo05 {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入账号");
        String name = scanner.next();
        System.out.println("请输入密码");
        String password = scanner.next();
        pdUser(name,password);
    }

    public static void pdUser(String name,String password){
    
    
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;

        try {
    
    
            DriverManager.registerDriver(new Driver());
            connection = DriverManager.getConnection(
                    "jdbc:mysql://localhost:3306/demo?useSSL=false", "root", "123456");

            statement = connection.createStatement();

            resultSet = statement.executeQuery("select * from user where NAME = '" + name +"' and PASSWORD = '" + password +"';");

            if (resultSet.next()){
    
    
                System.out.println("登录成功");
            } else {
    
    
                System.out.println("账号或密码错误");
            }

        } catch (Exception e) {
    
    

            try {
    
    
                resultSet.close();
            } catch (SQLException ex) {
    
    
                throw new RuntimeException(ex);
            }

            try {
    
    
                statement.close();
            } catch (SQLException ex) {
    
    
                throw new RuntimeException(ex);
            }

            try {
    
    
                connection.close();
            } catch (SQLException ex) {
    
    
                throw new RuntimeException(ex);
            }
        }
    }
}

注意:

  • 上面的代码中,SQL语句中我们使用拼接的方式,所以存在SQL注入的风险
  • 所以我们需要去改进SQL语句
8.1、PreparedStatement使用

PreparedStatement使用格式

  • SQL语句中的参数使用?作为占位符
  • 给?占位符赋值

设置参数

  • setXxx(参数1,参数2) ;Xxx代表数据类型
  • 参数1:第几个
  • 参数2:?的实际参数

执行SQL语句

  • int executeUpdate();执行insert、update、delete语句
  • ResultSet executeQuery();执行select语句

改进登陆案例

public class demo05 {
    
    
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入账号");
        String name = scanner.next();
        System.out.println("请输入密码");
        String password = scanner.next();
        pdUser(name,password);
    }

    public static void pdUser(String name,String password){
    
    
        Connection connection = null;
        ResultSet resultSet = null;
        PreparedStatement preparedStatement = null;

        try {
    
    
            DriverManager.registerDriver(new Driver());
            connection = DriverManager.getConnection(
                    "jdbc:mysql://localhost:3306/demo?useSSL=false", "root", "123456");

            String sql = "select * from user where name = ? and password = ?;";

            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,name);
            preparedStatement.setString(2,password);

            resultSet = preparedStatement.executeQuery();

            if (resultSet.next()){
    
    
                System.out.println("登录成功");
            } else {
    
    
                System.out.println("账号或密码错误");
            }

        } catch (Exception e) {
    
    

            try {
    
    
                if (resultSet != null){
    
    
                    resultSet.close();
                }
            } catch (SQLException ex) {
    
    
                throw new RuntimeException(ex);
            }

            try {
    
    
                preparedStatement.close();
            } catch (SQLException ex) {
    
    
                throw new RuntimeException(ex);
            }

            try {
    
    
                connection.close();
            } catch (SQLException ex) {
    
    
                throw new RuntimeException(ex);
            }
        }
    }
}

9、数据库连接池

数据库连接池简介

**连接池概念:**连接池就是一个容器,连接池中保存了一些数据库连接,这些连接是可以重复使用的

连接池原理:

  1. 启动数据库,连接池会初始化一些连接
  2. 当用户需要使用数据库连接,直接从连接池中取出
  3. 当用户使用完连接,会将连接重新放回连接池中

常用连接池介绍

javax.sql.DataSource表示数据库连接池,是JDK中提供的一个接口,没有具体的实现,它的实现是由连接池的厂商去实现,我们只需要学习这个工具即可

public interface DataSource{
    
    
	Connection getConmection();
}

常用的连接池实现组件:

  1. 阿里巴巴-德鲁伊Druid连接池:Druid是阿里巴巴开源平台上的项目
  2. C3P0是一个开源的连接池,目前使用它的开源项目有Hibernate,Spring等
  3. DBCP(DataBase Connection Pool)数据库连接池,是Tomcat使用的连接池组件
9.1、Druid连接池

Druid常用 的配置参数

方法名 说明
initialSize 刚启动连接池时,连接池中包含连接的数量
maxActive 连接池中最多可以放多少个连接
maxWait 获取连接时最大等待时间,单位毫秒

Druid连接池使用步骤

  1. 导入druid的jar包
  2. 设置properties文件
  3. 加载properties文件到Properties对象中
  4. 创建Druid连接池,使用配置文件中的参数
  5. 从Druid连接池中取出连接
  6. 执行SQL语句
  7. 关闭资源

案例代码

public class demo7 {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //加载properties文件的内容到Properties对象中
        Properties properties = new Properties();
        FileInputStream fileInputStream = new FileInputStream("src\\druid.properties");
        properties.load(fileInputStream);

        //创建连接池,使用配置文件中的参数
        DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

        //取出连接
        Connection connection = dataSource.getConnection();

        //执行sql语句
        String sql = "insert into user values(null,?,?);";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setString(1,"小陈");
        preparedStatement.setString(2,"1234");
        int row = preparedStatement.executeUpdate();
        System.out.println(row);

        //释放资源
        preparedStatement.close();
        //使用连接池之后,这里不是关闭,而是放回连接池
        connection.close();
    }
}
9.2、抽取工具类
public class getUtils {
    
    
    public static DataSource dataSource = null;
    static {
    
    
        try {
    
    
            Properties properties = new Properties();
            FileInputStream inputStream = new FileInputStream("src\\druid.properties");
            properties.load(inputStream);

            dataSource = DruidDataSourceFactory.createDataSource(properties);

        } catch (Exception e) {
    
    
            throw new RuntimeException(e);
        }
    }

    public static Connection getConnection() throws SQLException {
    
    
        return dataSource.getConnection();
    }


}

猜你喜欢

转载自blog.csdn.net/weixin_53961667/article/details/134158646