JDBC

1、JDBC简介

2、JDBC快速入门

3、JDBC API详解

  3.1 Driver Manager

    1. 注册驱动

    2. 获取连接

  3.2 Connection

    1. 获取执行SQL的对象

    2. 事务管理

  3.3 Statement

  3.4 ResultSet

  3.5 PreparedStatement

4、数据库连接池

  4.1 数据库库连接池简介

  4.2 Druid数据库连接池

  练习:完成商品品牌数据的增删改查操作

    1.数据准备

    2.查询数据

    3.添加数据

    4.修改数据

    5.删除数据

 

  

 

1、JDBC简介

JDBC概念:

  • JDBC就是使用Java语言操作关系型数据库的一套API
  • 全称:(Java DataBase Connectivity)Java数据库连接

JDBC本质:

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

JDBC好处:

  • 各个数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发
  • 可随时替换底层数据库,访问数据库的Java代码基本不变

2、JDBC快速入门

步骤:

  1. 注册驱动

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

  2. 获取连接

Connection conn = DriverManager.getConnection(url,username,password);

  3. 定义SQL语句

String sql = "update ...";

  4. 获取执行SQL对象

Statement stmt = conn.createStatement();

  5. 执行SQL

stmt.executeUpdate(sql);

  6. 处理·返回结果

  7. 释放资源

/*
    JDBC快速入门
* */
public class JDBCDemo {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");

        //2.获取连接
        String url = "jdbc:mysql://localhost:3306/db1";
        String username = "root";
        String password = "liming";
        Connection conn = DriverManager.getConnection(url, username, password);

        //3.定义SQL语句
        String sql = "update account set money = 2000 where id =1";

        //4.获取执行SQL的对象Statement
        Statement stmt = conn.createStatement();

        //5.执行sql
        int count = stmt.executeUpdate(sql);//受影响的行数

        //6.处理结果
        System.out.println(count);

        //7.释放资源
        stmt.close();
        conn.close();
    }
}

3、JDBC API详解

3.1 Driver Manager

  • DriverManager(驱动管理类)作用:

    1. 注册驱动

    2. 获取数据库连接

1. 注册驱动

Class.forName("com.mysql.jdbc.Driver");
  • 查看Drive类源码

  提示:

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

2. 获取连接

static Connection  getConnection(String url,String user,String  password)
    
  • 参数:
    • url:连接路径

        语法:jdbc:myslq://ip地址:端口号/数据库名称?参数键值对1&参数键值对2...

        示例:jdbc:mysql://127.0.0.1:3306/db1?useSSL=false

        细节:

        • 如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则可以简写为:jdbc:mysql:///数据库名称?参数键值对
        • 配置useSSL=false参数,禁用安全连接凡事,解决警告提示

 

    • user:用户名
    • password:密码
/*
    JDBC API 详解:DriverManager
* */
public class JDBCDemo2_DriverManager {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //2.获取连接:如果连接的是本机mysql,并且端口是默认的3306,可以简化书写
        String url = "jdbc:mysql:///db1?useSSL=false";
        String username = "root";
        String password = "liming";
        Connection conn = DriverManager.getConnection(url, username, password);

        //3.定义SQL语句
        String sql = "update account set money = 2000 where id =1";

        //4.获取执行SQL的对象Statement
        Statement stmt = conn.createStatement();

        //5.执行sql
        int count = stmt.executeUpdate(sql);//受影响的行数

        //6.处理结果
        System.out.println(count);

        //7.释放资源
        stmt.close();
        conn.close();
    }
}

3.2 Connection

  • Connection(数据库连接对象)作用:

    1. 获取执行SQL的对象

    2. 事务管理

1. 获取执行SQL的对象

  • 普通执行SQL对象

    Statement createStatement()

  • 预编译SQL的执行SQL对象:防止SQL注入

     PreparedStatement preparedStatement()

  • 执行存储过程的对象

    CallableStatement preparedCall(sql)

2. 事务管理

  • MySQL事务管理
开启事务:Begin;/start transaction;
提交事务:commit;
回滚事务:rollback;

MySQL默认自动提交事务
  • JDBC事务管理:Connetion接口中定义了3个对应的方法

    开启事务setAutoCommit(boolean autoCommit):ture为自动提交;false为手动提交,即为开启事务

    提交事务commit()  

    回滚事务rollback()

/*
    JDBC API 详解:Connection
* */
public class JDBCDemo3_Connection {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //2.获取连接:如果连接的是本机mysql,并且端口是默认的3306,可以简化书写
        String url = "jdbc:mysql:///db1?useSSL=false";
        String username = "root";
        String password = "liming";
        Connection conn = DriverManager.getConnection(url, username, password);

        //3.定义SQL语句
        String sql1 = "update account set money = 3000 where id =1";
        int i = 3/0;
        String sql2 = "update account set money = 3000 where id =2";


        //4.获取执行SQL的对象Statement
        Statement stmt = conn.createStatement();
        //开启事务
        conn.setAutoCommit(false);

        try {
            //5.执行sql
            int count1 = stmt.executeUpdate(sql1);//受影响的行数
            int count2 = stmt.executeUpdate(sql2);//受影响的行数

            //6.处理结果
            System.out.println(count1);
            System.out.println(count2);
            //提交事务
            conn.commit();
        } catch (Exception e) {
            //回滚事务
            conn.rollback();
            throw new RuntimeException(e);
        }

        //7.释放资源
        stmt.close();
        conn.close();
    }
}

3.3 Statement

  • Statement作用:

    1. 执行SQL语句

  • 执行SQL语句

    int executeUpdate(sql):执行DML、DDL语句

      返回值:(1)DML语句影响的行数 (2)DDL语句执行后,执行成功也可能返回0

    ResultSet executeQuery(sql):执行DQL语句

      返回值:ResultSet结果集对象

/*
    JDBC API 详解:Statement
* */
public class JDBCDemo4_Statement {
    /*
        执行DML语句
    * */
    @Test
    public void testDML() throws Exception {
        //2.获取连接:如果连接的是本机mysql,并且端口是默认的3306,可以简化书写
        String url = "jdbc:mysql:///db1?useSSL=false";
        String username = "root";
        String password = "liming";
        Connection conn = DriverManager.getConnection(url, username, password);

        //3.定义SQL语句
        String sql1 = "update account set money = 3000 where id =1";
        String sql2 = "update account set money = 3000 where id =2";


        //4.获取执行SQL的对象Statement
        Statement stmt = conn.createStatement();
        //开启事务
        conn.setAutoCommit(false);

        try {
            //5.执行sql
            int count1 = stmt.executeUpdate(sql1);//受影响的行数
            int count2 = stmt.executeUpdate(sql2);//受影响的行数

            //6.处理结果
            if (count1 > 0){
                System.out.println("执行成功");
            }else {
                System.out.println("执行失败");
            }
            if (count2 > 0){
                System.out.println("执行成功");
            }else {
                System.out.println("执行失败");
            }
            //提交事务
            conn.commit();
        } catch (Exception e) {
            //回滚事务
            conn.rollback();
            throw new RuntimeException(e);
        }

        //7.释放资源
        stmt.close();
        conn.close();
    }

    /*
        执行DDL语句
    * */
    @Test
    public void testDDL() throws Exception {
        //2.获取连接:如果连接的是本机mysql,并且端口是默认的3306,可以简化书写
        String url = "jdbc:mysql:///db1?useSSL=false";
        String username = "root";
        String password = "liming";
        Connection conn = DriverManager.getConnection(url, username, password);

        //3.定义SQL语句
        String sql = "drop database test";



        //4.获取执行SQL的对象Statement
        Statement stmt = conn.createStatement();
        //开启事务
        conn.setAutoCommit(false);

        try {
            //5.执行sql
            int count = stmt.executeUpdate(sql);//受影响的行数


            //6.处理结果
            System.out.println(count);

            //提交事务
            conn.commit();
        } catch (Exception e) {
            //回滚事务
            conn.rollback();
            throw new RuntimeException(e);
        }

        //7.释放资源
        stmt.close();
        conn.close();
    }
}

3.4 ResultSet

  • ResultSet(结果集对象)作用:

    ResultSet stmt.executeQuery(sql):执行DQL语句,返回ResultSet对象

  • 获取查询结果

    boolean next():(1)将光标从当前位置向前移动一行 (2)判断当前行是否为有效行

      返回值:

      • true:有效行,当前行有数据
      • false:吴晓航,当前行没有数据

    xxx getXxx(参数):获取数据

    • xxx:数据类型;如:int getInt(参数);String getString(参数)
    • 参数:
      • int:列的编号,从1开始
      • String:列的名称
/*
    JDBC API 详解:ResultSet
* */
public class JDBCDemo5_ResultSet {
    /*
        执行DML语句
    * */
    @Test
    public void testDML() throws Exception {
        //2.获取连接:如果连接的是本机mysql,并且端口是默认的3306,可以简化书写
        String url = "jdbc:mysql:///db1?useSSL=false";
        String username = "root";
        String password = "liming";
        Connection conn = DriverManager.getConnection(url, username, password);

        //3.定义SQL语句
        String sql = "select * from account";

        //4.获取Statement
        Statement stmt = conn.createStatement();

        //5.执行SQL
        ResultSet rs = stmt.executeQuery(sql);

        //6.处理结果
        while (rs.next()){
            int id = rs.getInt(1);
            String name = rs.getString(2);
            double money = rs.getDouble(3);
            System.out.println(id);
            System.out.println(name);
            System.out.println(money);
            System.out.println("-------");
        }
        
        //7.释放资源
        rs.close();
        stmt.close();
        conn.close();
    }
}

      

 案例:ResultSet案例

  需求:查询account账户表数据,封装为Account对象中,并且存储到ArrayList集合中

3.5 PreparedStatement

  • PreparedStatement作用:

    1. 预编译SQL语句并执行:预防SQL注入问题

    • 获取PreparedStatement对象
  •  
    //SQL语句中的参数值,使用?占位符替换
    String sql = "select * from tb_user where username = ? and password = ?";
    
    //通过Connection对象获取,并传入对应的sql语句
    PreparedStatement preparedStatement = conn.prepareStatement(sql);
    • 设置参数
    • PreparedStatement对象:setXxx(参数1,参数2):给?赋值

      • Xxx数据类型;如setInt(参数1,参数2)
      • 参数:
        • 参数1:?的位置编号,从1开始
        • 参数2:?的值
    • 执行SQL

      executeUpdate();/executeQuery():不需要再传递sql

  • SQL注入
    • SQL注入是通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对于服务器进行攻击的方法。

步骤:SQL注入演示

  需求:完成用户登录

select * from tb_user where username= 'zhangsan' and password = '123';
/*
    JDBC API 详解:ResultSet
* */
public class JDBCDemo6_UserLogin {
    /*
        执行DML语句
    * */
    @Test
    public void testDML() throws Exception {
        //2.获取连接:如果连接的是本机mysql,并且端口是默认的3306,可以简化书写
        String url = "jdbc:mysql:///test?useSSL=false";
        String username = "root";
        String password = "liming";
        Connection conn = DriverManager.getConnection(url, username, password);

        //3.定义SQL语句
        String name = "zhangsan";
        String pwd = "' or '1' = '1";
        String sql = "select * from tb_user where username = '"+name+"' and password = '"+pwd+"'";

        //4. 获取Statement
        Statement stmt = conn.createStatement();

        //5. 执行SQL
        ResultSet rs = stmt.executeQuery(sql);

        //6.处理结果
        while (rs.next()){
            int id = rs.getInt("id");
            String uname = rs.getString("username");
            String pw = rs.getString("password");
            System.out.println(id);
            System.out.println(uname);
            System.out.println(pw);

        }

        //7.释放资源
        stmt.close();
        conn.close();
    }
}
/*
    JDBC API 详解:PreparedStatement
* */
public class JDBCDemo7_UserLogin {
    /*
        执行DML语句
    * */
    @Test
    public void testDML() throws Exception {
        //2.获取连接:如果连接的是本机mysql,并且端口是默认的3306,可以简化书写
        String url = "jdbc:mysql:///test?useSSL=false";
        String username = "root";
        String password = "liming";
        Connection conn = DriverManager.getConnection(url, username, password);

        //3.定义SQL语句
        String name = "zhangsan";
        String pwd = "123";
//        String sql = "select * from tb_user where username = '"+name+"' and password = '"+pwd+"'";
        String sql = "select * from tb_user where username = ? and password = ?";

        //4. 获取PreparedStatement
        PreparedStatement pstmt = conn.prepareStatement(sql);
        pstmt.setString(1,name);
        pstmt.setString(2,pwd);

        //5. 执行SQL
        ResultSet rs = pstmt.executeQuery();

        //6.处理结果
        while (rs.next()){
            int id = rs.getInt("id");
            String uname = rs.getString("username");
            String pw = rs.getString("password");
            System.out.println(id);
            System.out.println(uname);
            System.out.println(pw);

        }

        //7.释放资源
        pstmt.close();
        conn.close();
    }
}

4、数据库连接池

4.1 数据库库连接池简介

  • 数据库连接池是个容器,负责分配、管理数据库连接(Connection)
  • 他允许应用程序重复使用一个现有的1数据库连接,而不是重新建立一个。
  • 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏
  • 好处:
    • 资源重用
    • 提升系统响应速度
    • 皮面数据库连接遗漏

 

4.2 Druid数据库连接池

  • 标准接口:DataSource
    • 官方(SUN)提供的数据库连接池标准接口,由第三方组织实现接口。
    • 功能:获取连接

        Connection getConnection()

  • 常见的数据库连接池:
    • DBCP
    • C3P0
    • Druid
  • Druid(德鲁伊)
    • Druid连接池是阿里巴巴开源的数据可连接池之一
    • 功能强大,性能优秀,是Java语言最好的数据库连接池之一

步骤:Druid使用步骤

  1. 导入jar包druid-1.1.12.jar

  2. 定义配置文件

  3. 加载配置文件

  4. 获取数据库连接池对象

  5. 获取连接

public class DruidDemo {
    public static void main(String[] args) throws Exception {
        //1.导入Jar包
        //2.定义配置文件

        //3.加入配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));
        //4.获取连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);

        //5. 获取数据连接
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
    }
}

练习:完成商品品牌数据的增删改查操作

  • 查询:查询所有数据
  • 添加:添加品牌
  • 修改:根据id修改
  • 删除:根据id删除

  1. 环境准备

    • 数据库表 tb_brand
  • -- 删除tb_brand表
    drop table if exists tb_brand;
    -- 创建tb_brand表
    create table tb_brand (
    -- id 主键
    id int primary key auto_increment,
    -- 品牌名称
    brand_name varchar(20),
    -- 企业名称
    company_name varchar(20),
    -- 排序字段
    ordered int,
    -- 描述信息
    description varchar(100),
    -- 状态:0:禁用 1:启用
    status int
    );
    -- 添加数据
    insert into tb_brand (brand_name, company_name,
    ordered, description, status)
    values ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上
    火', 0),
    ('华为', '华为技术有限公司', 100, '华为致力于把
    数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世
    界', 1),
    ('小米', '小米科技有限公司', 50, 'are you ok',
    1);
    • 在pojo包下实体类Brand
public class Brand {
    private Integer id;
    // 品牌名称
    private String brand_name;
    // 企业名称
    private String company_name;
    // 排序字段
    private Integer ordered;
            // 描述信息
    private String description;
    // 状态:0:禁用 1:启用
    private Integer status;

    public Brand() {
    }

    public Brand(Integer id, String brand_name, String company_name, Integer ordered, String description, Integer status) {
        this.id = id;
        this.brand_name = brand_name;
        this.company_name = company_name;
        this.ordered = ordered;
        this.description = description;
        this.status = status;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getBrand_name() {
        return brand_name;
    }

    public void setBrand_name(String brand_name) {
        this.brand_name = brand_name;
    }

    public String getCompany_name() {
        return company_name;
    }

    public void setCompany_name(String company_name) {
        this.company_name = company_name;
    }

    public Integer getOrdered() {
        return ordered;
    }

    public void setOrdered(Integer ordered) {
        this.ordered = ordered;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    @Override
    public String toString() {
        return "Brand{" +
                "id=" + id +
                ", brand_name='" + brand_name + '\'' +
                ", company_name='" + company_name + '\'' +
                ", ordered=" + ordered +
                ", description='" + description + '\'' +
                ", status=" + status +
                '}';
    }
}

  2. 查询数据

//查询数据
    @Test
    public void selectAll() throws Exception {
        //加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream("src/druid.properties"));

        //获取连接池
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
        Connection conn = dataSource.getConnection();

        //获取preparedStatement
        String sql = "select * from tb_brand";
        PreparedStatement pstmt = conn.prepareStatement(sql);

        //执行SQL
        ResultSet rs = pstmt.executeQuery();
        //处理结果
        List<Brand> brands = new ArrayList<>();
        while (rs.next()){
            int id = rs.getInt("id");
            String brand_name = rs.getString("brand_name");
            String company_name = rs.getString("company_name");
            int ordered = rs.getInt("ordered");
            String description = rs.getString("description");
            int status = rs.getInt("status");
            Brand brand = new Brand(id, brand_name, company_name, ordered, description, status);
            brands.add(brand);
        }
        System.out.println(brands);

        //释放资源
        rs.close();
        pstmt.close();
        conn.close();
    }

  3. 添加数据

//添加数据
    @Test
    public void insert() throws Exception {
        //加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream("src/druid.properties"));

        //获取连接池
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
        Connection conn = dataSource.getConnection();

        //获取preparedStatement
        String sql = "insert into tb_brand(brand_name,company_name,ordered,description,status) values(?,?,?,?,?)";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        pstmt.setString(1,"OPPO");
        pstmt.setString(2,"OPPO技术有限公司");
        pstmt.setInt(3,20);
        pstmt.setString(4,"蓝绿厂");
        pstmt.setInt(5,1);

        //执行SQL
        int count = pstmt.executeUpdate();
        //处理结果
        System.out.println(count);

        //释放资源
        pstmt.close();
        conn.close();
    }

  4. 修改数据

//修改数据
    @Test
    public void updateById() throws Exception {
        System.out.println(System.getProperty("user.dir"));
        //加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream("src/druid.properties"));

        //获取连接池
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
        Connection conn = dataSource.getConnection();

        //获取preparedStatement
        String sql = "update tb_brand set description = ? where id = ?";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        pstmt.setString(1,"雷总,are you ok");
        pstmt.setInt(2,3);
        //执行SQL
        int count = pstmt.executeUpdate();

        //处理结果

        System.out.println(count);

        //释放资源
        pstmt.close();
        conn.close();
    }

  5. 删除数据

//删除数据
    @Test
    public void deleteById() throws Exception {
        System.out.println(System.getProperty("user.dir"));
        //加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream("src/druid.properties"));

        //获取连接池
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
        Connection conn = dataSource.getConnection();

        //获取preparedStatement
        String sql = "delete from tb_brand where id = ?";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        pstmt.setInt(1,4);

        //执行SQL
        int count = pstmt.executeUpdate();

        //处理结果
        System.out.println(count);

        //释放资源
        pstmt.close();
        conn.close();
    }

  

 
 

 

 

posted @ 2023-08-25 18:18  mqBolg  阅读(8)  评论(0)    收藏  举报