day03 JDBC

目录

1. JDBC概述

2. 通过Java操作数据库的流程

2.1 编写代码步骤

2.2 API详解

2.2.1 获取执行对象

2.2.2 事务管理

3. 执行sql语句

3.1 执行DML语句

3.2 执行DDL语句

3.3 执行DQL语句

3.4 案例

4. SQL注入

4.1 SQL注入的原因

4.2 PreparedStatement概述

4.2.1 获取 PreparedStatement 对象

4.2.2 设置参数值

4.2.3 执行SQL语句

4.2.4 使用PreparedStatement改进

4.2.5 PreparedStatement防止注入的原理

5. 数据库连接池

5.1 数据库连接池简介

5.2 数据库连接池实现

5.3 Driud使用

5.3.1 Driud数据库连接池的实现

6. 练习

6.1 查询数据

6.2 添加数据

6.3 修改数据

6.4 删除数据


1. JDBC概述

JDBC就是使用Java语言操作关系型数据库的一套API

全称:( Java DataBase Connectivity ) Java 数据库连接

接口的实现类就叫驱动 

各个数据库厂商去实现这套接口,提供数据库驱动jar包,真正执行的代码是驱动 jar包中的实现类

如果需要操作MySQL数据库,就需要在项目中导入MySQL数据库的驱动包。

2. 通过Java操作数据库的流程

第一步:编写Java代码

第二步:Java代码将SQL发送到MySQL服务端

第三步:MySQL服务端接收到SQL语句并执行该SQL语句

第四步:将SQL语句执行的结果返回给Java代码

2.1 编写代码步骤

1. 创建工程,导入驱动jar包

2. 注册驱动

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

3. 获取连接

url : 连接路径

语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数 键值对

如 : jdbc:mysql://127.0.0.1:3306/db1

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

如 : jdbc:mysql://127.0.0.1:3306/db1?useSSL=false

Connection(数据库连接对象)

作用:1. 获取执行 SQL 的对象     2. 管理事务 

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

4. 定义SQL语句

String sql = “update…” ;

5. 获取执行SQL对象

执行SQL语句需要SQL执行对象,而这个执行对象就是 Statement对象

Statement stmt = conn.createStatement();

6. 执行SQL

stmt.executeUpdate(sql);  

7. 处理返回结果

8. 释放资源

代码示例

public class JDBCDemo {
    public static void main(String[] args) throws Exception {
        //1. 注册驱动
        Class.forName("com.mysql.jdbc.Driver");

        //2. 获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/db1";
        String username = "root";
        String password = "1234";
        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();
   }
}

2.2 API详解

2.2.1 获取执行对象

1. 普通执行SQL对象

Statement createStatement()

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

PreparedStatement prepareStatement(sql)

2.2.2 事务管理

MySQL事务管理的操作:

开启事务 : BEGIN; 或者 START TRANSACTION;

提交事务 : COMMIT;

回滚事务 : ROLLBACK;

MySQL默认是自动提交事务

如果手动开始事务, MySQL将不会自动提交事务, 则需要手动提交

3. 执行sql语句

3.1 执行DML语句

代码示例

public void testDML() throws  Exception {
    //1. 注册驱动
    //Class.forName("com.mysql.jdbc.Driver");

    //2. 获取连接:如果连接的是本机mysql并且端口是默认的3306 可以简化书写
    String url = "jdbc:mysql:///db1?useSSL=false";
    String username = "root";
    String password = "1234";
    Connection conn = DriverManager.getConnection(url, username,password);

    //3. 定义sql
    String sql = "update account set money = 3000 where id = 1";

    //4. 获取执行sql的对象 Statement
    Statement stmt = conn.createStatement();
    
    //5. 执行sql
    int count = stmt.executeUpdate(sql);//执行完DML语句,返回受影响的行数

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

    if(count > 0){
        System.out.println("修改成功~");
   }else{
        System.out.println("修改失败~");
   }
    //7. 释放资源
    stmt.close();
    conn.close();
}

3.2 执行DDL语句

executeUpdate(sql);

代码示例

public void testDDL() throws  Exception {
    //1. 注册驱动
    //Class.forName("com.mysql.jdbc.Driver");

    //2. 获取连接:如果连接的是本机mysql并且端口是默认的3306 可以简化书写
    String url = "jdbc:mysql:///db1?useSSL=false";
    String username = "root";
    String password = "1234";

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

    //3. 定义sql

    String sql = "drop database db2";

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

    //5. 执行sql
    int count = stmt.executeUpdate(sql);//执行完DDL语句,可能是0

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

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

3.3 执行DQL语句

ResultSet(结果集对象)

作用: 封装了SQL查询语句的结果。

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

1. boolean next()

将光标从当前位置向前移动一行

判断当前行是否为有效行

方法返回值说明:

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

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

2. xxx getXxx(参数):获取数据

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

代码示例

public void testResultSet() throws  Exception {
    //1. 注册驱动
    //Class.forName("com.mysql.jdbc.Driver");

    //2. 获取连接:如果连接的是本机mysql并且端口是默认的3306 可以简化书写
    String url = "jdbc:mysql:///db1?useSSL=false";
    String username = "root";
    String password = "1234";
    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. 处理结果, 遍历rs中的所有数据
    // 6.1 光标向下移动一行,并且判断当前行是否有数据

        while (rs.next()){

    //6.2 获取数据 getXxx()
        int id = rs.getInt("id");
        String name = rs.getString("name");
        double money = rs.getDouble("money");

        System.out.println(id);
        System.out.println(name);
        System.out.println(money);
       
   }
    //7. 释放资源
    rs.close();
    stmt.close();
    conn.close();
}

3.4 案例

需求:

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

 步骤

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

* 1. 定义实体类Account  

* 2. 查询数据,封装到Account对象中  

* 3. 将Account对象存入ArrayList集合中

代码示例

public void testResultSet2() throws  Exception {

    //1. 注册驱动
    //Class.forName("com.mysql.jdbc.Driver");

    //2. 获取连接:如果连接的是本机mysql并且端口是默认的3306 可以简化书写
    String url = "jdbc:mysql:///db1?useSSL=false";
    String username = "root";
    String password = "1234";
    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.创建集合
    List<Account> list = new ArrayList<>();
  
    // 6.1 光标向下移动一行,并且判断当前行是否有数据
    while (rs.next()){
        Account account = new Account();

        //6.2 获取数据 getXxx()
        int id = rs.getInt("id");
        String name = rs.getString("name");
        double money = rs.getDouble("money");
        //6.3 赋值
        account.setId(id);
        account.setName(name);
        account.setMoney(money);

        //6.4 存入集合
        list.add(account);
   }
    System.out.println(list);
    //7. 释放资源
    rs.close();
    stmt.close();
    conn.close();
}

4. SQL注入

4.1 SQL注入的原因

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

用户名随意写,密码写成 ' or '1' ='1

代码示例

    // 接收用户输入 用户名和密码
    String name = "sjdljfld";
    String pwd = "' or '1' = '1";

    String sql = "select * from tb_user where 
    username = '"+name+"' and password = '"+pwd+"'";

    // 获取stmt对象
    Statement stmt = conn.createStatement();
    // 执行sql
    ResultSet rs = stmt.executeQuery(sql);
String sql = "select * from tb_user where  username = '"+name+"' and password = '"+pwd+"'";

在这里密码写成 ' or '1' ='1,where后面的条件就会永远是true, 不论用户名是什么,都会成功执行sql

注入原因 字符串的拼接问题

4.2 PreparedStatement概述

PreparedStatement作用:

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

4.2.1 获取 PreparedStatement 对象

SQL语句中的参数值,使用占位符 ?替代。

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

通过Connection对象获取,并传入对应的sql语句

PreparedStatement pstmt = conn.prepareStatement(sql);

4.2.2 设置参数值

PreparedStatement对象:setXxx(参数1,参数2):给 ? 赋 值

Xxx:数据类型 ;

如 setInt (参数1,参数2)

参数1是 ?的位置编号,从1 开始

参数2是 ?的值

4.2.3 执行SQL语句

executeUpdate(); 执行DDL语句和DML语句

executeQuery(); 执行DQL语句

        调用这两个方法时不需要传递SQL语句,因为获取SQL语 句执行对象时已经对SQL语句进行预编译了。

4.2.4 使用PreparedStatement改进

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

    // 接收用户输入 用户名和密码
    String name = "zhangsan";
    String pwd = "' or '1' = '1";

    // 定义sql
    String sql = "select * from tb_user where username = ? and password = ?";

    // 获取pstmt对象
    PreparedStatement pstmt = conn.prepareStatement(sql);

    // 设置?的值
    pstmt.setString(1,name);
    pstmt.setString(2,pwd);

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

    // 判断登录是否成功
    if(rs.next()){
        System.out.println("登录成功~");
   }else{
        System.out.println("登录失败~");
   }

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

4.2.5 PreparedStatement防止注入的原理

将敏感字符进行转义

'\'or \'1\' = \'1'

5. 数据库连接池

5.1 数据库连接池简介

数据库连接池是个容器,负责分配、管理数据库连接

作用:

资源重用

提升系统响应速度

避免数据库连接遗漏

        连接池是在一开始就创建好了一些连接(Connection)对象存储起 来。用户需要连接数据库时,不需要自己创建连接,而只需要从连 接池中获取一个连接进行使用,使用完毕后再将连接对象归还给连 接池;这样就可以起到资源重用,也节省了频繁创建连接销毁连接 所花费的时间,从而提升了系统响应的速度。

5.2 数据库连接池实现

标准接口:DataSource

实现此接口的方法

Connection getConnection()

        以后就不需要通过 DriverManager 对象获取 Connection 对象,而是通过连接池(DataSource)获取 Connection 对 象。

Druid(德鲁伊)

Druid连接池是阿里巴巴开源的数据库连接池项目

功能强大,性能优秀,是Java语言最好的数据库连接池之一

5.3 Driud使用

导入jar包 druid-1.1.12.jar

定义配置文件

加载配置文件

获取数据库连接池对象

获取连接

5.3.1 Driud数据库连接池的实现

代码示例

public class DruidDemo {
    public static void main(String[] args) throws Exception {
        //1.导入jar包
        //2.定义配置文件
        //3. 加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream("druid.properties"));

        //4. 获取连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);

        //5. 获取数据库连接 Connection
        Connection connection = dataSource.getConnection();

        System.out.println(connection); 

        //获取到了连接后就可以继续做其他操作了

    }
}

6. 练习

需求

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

查询:查询所有数据

添加:添加品牌 

修改:根据id修改

删除:根据id删除

1. 创建数据库表 tb_brand

2. 在pojo包(javaBean类存放的包)下实体类 Brand

6.1 查询数据

public void testSelectAll() throws Exception {
    //3. 加载配置文件
    Properties prop = new Properties();
    prop.load(new FileInputStream("jdbcdemo/src/druid.properties"));

    //4. 获取连接池对象
    DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);

    //5. 获取数据库连接 Connection
    Connection conn = dataSource.getConnection();

    //6. 定义SQL
    String sql = "select * from tb_brand";

    //7. 获取pstmt对象
    PreparedStatement pstmt = conn.prepareStatement(sql);

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

    //9. 处理结果 List<Brand> 封装Brand对象,装载List集合
    Brand brand = null;
    List<Brand> brands = new ArrayList<>();
    while (rs.next()){

        //获取数据
        int id = rs.getInt("id");
        String brandName = rs.getString("brand_name");
        String companyName = rs.getString("company_name");
        int ordered = rs.getInt("ordered");
        String description = rs.getString("description");
        int status = rs.getInt("status");

        //封装Brand对象
        brand = new Brand();

        //赋值
        brand.setId(id);
        brand.setBrandName(brandName);
        brand.setCompanyName(companyName);
        brand.setOrdered(ordered);
        brand.setDescription(description);
        brand.setStatus(status);

        //装载集合
        brands.add(brand);
   }

    System.out.println(brands);

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

6.2 添加数据

public void testAdd() throws Exception {

    // 接收页面提交的参数
    String brandName = "香飘飘";
    String companyName = "香飘飘";
    int ordered = 1;
    String description = "绕地球一圈";
    int status = 1;

    //加载配置文件
    Properties prop = new Properties();
    prop.load(new FileInputStream("jdbcdemo/src/druid.properties"));

    //获取连接池对象
    DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);

    //获取数据库连接 Connection
    Connection conn = dataSource.getConnection();
    //定义SQL
    String sql = "insert into tb_brand(
                brand_name, 
                company_name, 
                ordered, 
                description, 
                status)
                    values(?,?,?,?,?)";

    //获取pstmt对象
    PreparedStatement pstmt = conn.prepareStatement(sql);

    //设置参数
    pstmt.setString(1,brandName);
    pstmt.setString(2,companyName);
    pstmt.setInt(3,ordered);
    pstmt.setString(4,description);
    pstmt.setInt(5,status);
    //执行SQL

    int count = pstmt.executeUpdate(); // 影响的行数

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

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

6.3 修改数据

6.4 删除数据

public void testDeleteById() throws Exception {
    // 接收页面提交的参数

    int id = 4;
    //获取Connection
    //加载配置文件
    Properties prop = new Properties();
    prop.load(new FileInputStream("jdbcdemo/src/druid.properties"));

    //获取连接池对象
    DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);

    //获取数据库连接 Connection
    Connection conn = dataSource.getConnection();

    //定义SQL
    String sql = " delete from tb_brand where id = ?";

    //获取pstmt对象
    PreparedStatement pstmt = conn.prepareStatement(sql);

    //设置参数
    pstmt.setInt(1,id);

    //执行SQL
    int count = pstmt.executeUpdate(); // 影响的行数

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值