JAVA WEB重学day11


学习目标

  • 能够理解JDBC的概念
  • 能够使用Connection接口
  • 能够使用Statement接口
  • 能够使用ResultSet接口
  • 能够使用JDBC实现对单表数据增、删、改、查
  • 能够使用JDBC操作事务
  • 能够完成JDBC实现登录案例
  • 能够使用C3P0连接池
  • 能够使用DRUID连接池
  • 能够编写连接池工具类

JDBC概述

  1. JDBC是什么
    英文全称:Java DataBase Connectivity
    中文全称:Java 数据库连接技术

  2. JDBC的作用
    与数据库建立连接并对数据库执行操作:增删改查操作

  3. JDBC的组成
    由一组官方定义的接口(规范)组成:接口的实现类由数据库厂商提供:数据库驱动(包含实现操作数据库接口的类)

  4. JDBC的好处
    代码不依赖于任何数据库。
    只需要修改少量配置就可以方便切换到其他厂商数据库。

JDBC核心类和接口说明
DriverManager 工具类1. 用于注册数据库驱动
2. 用于获取连接对象
Connection 接口连接对象
作用:与数据库建立连接并形成数据传输通道
Statement 接口SQL语句发送对象
作用:将SQL语句发送给数据库执行并获得执行结果
ResultSet 接口结果集对象
作用:用来封装满足查询条件的记录信息。
Drvier 接口数据库驱动对象

JDBC之注册驱动

在这里插入图片描述

注册驱动方法说明
static registerDriver(Driver driver)驱动会注册两次
Class.forName(“com.mysql.jdbc.Driver”);只会注册一次

JDBC之获取连接对象

/**
目标:与数据库建立连接并获得Connection对象

DriverManager工具类与获得连接对象相关的方法
* static Connection getConnection(String url, String user, String password)
* 与数据库建立连接并返回连接对象
* url: 数据库连接字符串
* user: 用户名 root
* password: 密码 root

* static Connection	getConnection(String url, Properties info)
    * 与数据库建立连接并返回连接对象
    * url: 数据库连接字符串
    * info: 属性集合(双列集合,用法和map一样):用来存储用户名和密码
        * 可以将用户名和密码配置在文件中


数据库连接字符串格式:
    完整格式:JDBC协议:子协议://数据库服务器地址:端口号/数据库名
        * JDBC协议:固定值是:jdbc
        * 子协议:一般是数据库厂商的名字,比如mysql或oracle
    省略格式:JDBC协议:子协议:/// 数据库名
        * 前提条件:操作本机数据库且端口号是默认值3306


MySQL数据库连接字符串完整格式:jdbc:mysql://localhost:3306/day11
MySQL数据库连接字符串省略格式:jdbc:mysql:///day11

*/

DriverManager类与数据库建立连接的方法说明
static Connection getConnetion(
String url,
String username,
String password)
获得连接对象
url:连接字符串
username:用户名
password:密码
static Connection getConnection(
String url, Properties info)
获得连接对象

JDBC之Statement对象概述

  • Statement对象的作用:将SQL语句发送给数据库执行并获取结果
  • 如何获得Statement对象:通过连接对象的方法获得:Statement createStatement();
Statement对象常用方法说明
boolean execute(String sql)可以执行任意SQL语句
一般用来执行DDL语句:创库或创表
int executeUpdate(String sql)用于执行增删改语句:返回影响的行数
只要不是查询都称为更新操作
ResultSet executeQuery(String sql)用于执行查询语句

JDBC之执行DDL语句_创建表

使用JDBC在数据库创建数据表的步骤

  1. 注册驱动:Class.forName(“驱动类全名字符串”);
  2. 获得连接对象:Connection conn = DriverManger.getConnection(“连接字符串”,“用户名”,“密码”);
  3. 获得SQL语句发送对象:Statement stmt = conn.createStatement();
  4. 准备SQL语句:String sql="…";
  5. 调用SQL语句发送对象的方法:stmt.execute…(sql);
  6. 关闭连接释放资源

在这里插入图片描述

JDBC之执行DML语句_增删改

/**
目标:使用JDBC实现增删改功能
*/
public class Demo01 {
public static void main(String[] args) throws Exception{
// 插入数据
// testInsert();

    // 更新数据
    // testUpdate();

    // 删除数据
    testDelete();
}



// 插入数据
public static void testInsert()throws Exception{
    // 1. 注册驱动
    Class.forName("com.mysql.jdbc.Driver");
    // 2. 获得连接对象
    Connection conn = DriverManager.getConnection("jdbc:mysql:///day11", "root", "root");
    // 3. 获得SQL语句发送对象
    Statement stmt = conn.createStatement();
    // 4. 准备SQL语句
    String sql = "insert into student values(null,'rose','女','2000-12-20'),(null,'luck','男','1990-02-21');";
    // 5. 调用SQL语句发送对象的方法
    int row = stmt.executeUpdate(sql);
    System.out.println("row = " + row);
    // 6. 关闭连接释放资源
    stmt.close();
    conn.close();
}

// 修改数据:将id为3的学生性别修改为女,姓名修改为:lily
public static void testUpdate()throws Exception{
    // 1. 注册驱动
    Class.forName("com.mysql.jdbc.Driver");
    // 2. 获得连接对象
    Connection conn = DriverManager.getConnection("jdbc:mysql:///day11", "root", "root");
    // 3. 获得SQL语句发送对象
    Statement stmt = conn.createStatement();
    // 4. 准备SQL语句
    String sql = "update student set gender = '女', name='lily' where id = 3;";
    // 5. 调用SQL语句发送对象的方法
    int row = stmt.executeUpdate(sql);
    System.out.println("row = " + row); // 1
    // 6. 关闭连接释放资源
    stmt.close();
    conn.close();
}

// 删除数据:把id为2的学生删除
public static void testDelete() throws Exception{
    // 1. 注册驱动
    Class.forName("com.mysql.jdbc.Driver");
    // 2. 获得连接对象
    Connection conn = DriverManager.getConnection("jdbc:mysql:///day11", "root", "root");
    // 3. 获得SQL语句发送对象
    Statement stmt = conn.createStatement();
    // 4. 准备SQL语句
    String sql = "delete from student where id = 2";
    // 5. 调用SQL语句发送对象的方法
    int row = stmt.executeUpdate(sql);
    System.out.println("row = " + row); // 1
    // 6. 关闭连接释放资源
    stmt.close();
    conn.close();
}

JDBC之执行DQL语句_查询数据

/**
目标:使用JDBC实现查询功能
需求:查询所有学生信息并输出到控制台

注意事项:
1. 当指针执行结果集的第一行之前,调用了getXxx方法获取数据则会出现下面异常:
java.sql.SQLException: Before start of result set
2. 当指针执行结果集的最后一行之后,调用了getXxx方法获取数据则会出现下面异常:
java.sql.SQLException: After end of result set
*/
public class Demo01 {
public static void main(String[] args) throws Exception {
// 1. 注册驱动
Class.forName(“com.mysql.jdbc.Driver”);
// 2. 获得连接对象
Connection conn = DriverManager.getConnection(“jdbc:mysql:///day11”, “root”, “root”);
// 3. 获得SQL语句发送对象
Statement stmt = conn.createStatement();
// 4. 准备SQL语句
String sql = “select * from student”;
// 5. 执行SQL语句并获得结果集对象
ResultSet rs = stmt.executeQuery(sql);

    // 循环获取每一行数据
    // 将指针下移一行、
    while(rs.next()){
        // 根据列号获取每一列的值
       /* int id = rs.getInt(1);
        String name = rs.getString(2);
        String gender = rs.getString(3);
        String birthday = rs.getString(4);*/

        // 根据列名获取每一列的值
        int id = rs.getInt("id");
        String name = rs.getString("name");
        String gender = rs.getString("gender");
        Date birthday = rs.getDate("birthday");

        System.out.println(id+","+name+","+gender+"," + birthday);
    }

    // 6. 关闭连接释放资源
    rs.close();
    stmt.close();
    conn.close();
}

JDBC事务-转账案例

步骤分析

  1. 注册驱动
  2. 获得连接对象并开启事务
  3. 获取SQL发送对象
  4. 准备扣钱SQL语句
  5. 执行扣钱SQL语句
  6. 准备加钱SQL语句
  7. 执行加钱SQL语句
  8. 如果没有问题则提交事务,否则回滚事务
  9. 关闭资源

/**
目标:使用JDBC实现事务管理
需求:Jack给rose转500块

实现步骤
1. 注册驱动
2. 获得连接对象
3. 获取SQL发送对象
4. 准备扣钱SQL语句
5. 执行扣钱SQL语句
6. 准备加钱SQL语句
7. 执行加钱SQL语句
8. 关闭资源

Connection对象与事务管理相关的方法
* void setAutoCommit(boolean b)
* 设置是否自动提交事务
* b:true 自动提交,默认值
* b:false 禁止自动提交 ==> 相当于start transaction;手动开启事务
* void commit();
* 提交事务
* void rollback();
* 回滚事务
*/
public class Demo01 {
public static void main(String[] args){
// 声明连接对象
Connection conn = null;
Statement stmt = null;
try{
// 1. 注册驱动
Class.forName(“com.mysql.jdbc.Driver”);
// 2. 获得连接对象
conn = DriverManager.getConnection(“jdbc:mysql:///day11”, “root”, “root”);

       // 开启事务:等价start transaction;
       conn.setAutoCommit(false);

       // 3. 获取SQL发送对象
       stmt = conn.createStatement();
       // 4. 准备扣钱SQL语句
       String sql01 = "update account set balance = balance - 500 where id = 1";
       // 5. 执行扣钱SQL语句
       int row = stmt.executeUpdate(sql01);
       System.out.println("扣钱:" + row);

       // 模拟异常
       System.out.println(10/0);

       // 6. 准备加钱SQL语句
       String sql02 = "update account set balance = balance + 500 where id = 2";
       // 7. 执行加钱SQL语句
       row = stmt.executeUpdate(sql02);
       System.out.println("加钱:" + row);
       // 提交事务
       conn.commit();
   } catch(Exception e){
       System.out.println("回滚了事务...");
        try {
            if (conn != null)
                conn.rollback(); // 回滚事务
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    } finally {
        // 8. 关闭资源
        if (stmt != null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn !=null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
Connection接口中与事务相关的方法说明
void setAutCommit(boolean b);设置是否自动提交事务,默认是true:自动提交
false:禁止自动提交,需要手动提交
void commit()提交事务
void rollback()回滚事务

创建JDBC工具类

创建工具类的目的:将重复的代码定义到某个类的方法中,直接调用方法,可以简化代码。

实现工具类的步骤
1. 将固定字符串定义为常量
2. 在静态代码块中注册驱动(只注册一次)
3. 提供一个获取连接的方法:static Connection getConneciton();
4. 定义关闭资源的方法:close(Connection conn, Statement stmt, ResultSet rs)
5. 重载关闭方法:close(Connection conn, Statement stmt)

public class JDBCUtil {

// 1. 将固定字符串定义为常量
private static final String DRIVER_CLASS = "com.mysql.jdbc.Driver";
private static final String URL = "jdbc:mysql:///day11";
private static final String USER = "root";
private static final String PASSWORD = "root";

/**
 * 2. 在静态代码块中注册驱动(只注册一次)
 */
static {
    try {
        // 1. 注册驱动
        Class.forName(DRIVER_CLASS);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

/*
* 3. 提供一个获取连接的方法:static Connection getConnection();
* */
public static Connection getConnection() {

  try{
      return DriverManager.getConnection(URL, USER,PASSWORD);
  } catch(Exception e){
      // return null;
      // 将编译时异常包装成运行时异常
      throw new RuntimeException(e);
  }
}

// 4. 定义关闭资源的方法:close(Connection conn, Statement stmt, ResultSet rs)
public static void close(Connection conn, Statement stmt, ResultSet rs){
    /**
     关闭资源注意事项:先开后关(先创建的后关闭)
     1. 创建顺序:Connection ==> Statement ==> ResultSet
     2. 关闭顺序:ResultSet ==> Statement ==> Connectio
     */
    if (rs != null) {
        try {
            rs.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    if (stmt != null){
        try {
            stmt.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    if (conn !=null) {
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

//  5. 重载关闭方法:close(Connection conn, Statement stmt)
public static void close(Connection conn, Statement stmt){
    close(conn, stmt, null);
}

PreparedStatement和Statement区别

相同点
都可以对数据库执行增删改查操作。

不同点
1. PreparedStatement有预编译功能,Statement没有预编译功能。
2. PreparedStatement有缓存功能(缓存SQL语句的编译结果),Statement没有缓存功能。
3. PreparedStatement没有SQL注入,更安全,Statement有SQL注入,不安全。

PreparedStatement实现增删改操作

PreparedStatement实现增删改的步骤

  1. 获得连接对象
  2. 准备SQL语句:未知内容使用占位符?代替
  3. 根据SQL获得预编译对象
  4. 给占位符?赋值
  5. 执行SQL语句并获得结果
  6. 释放资源

public class Demo01 {

public static void main(String[] args) throws Exception{
    // 添加数据: 向学生表添加3条记录
    // insertStudent();

    // 修改数据: 将 id 为 2的用户,姓名更新为 "嫦娥 "  性别换成女,
    // updateStudent();

    // 删除数据: 删除id为2的学生
    deleteStudent();
}

// 添加数据: 向学生表添加3条记录
public static void insertStudent() throws Exception {
    // 1. 获得连接对象
    Connection conn = JDBCUtil.getConnection();
    // 2. 准备SQL语句:未知内容使用占位符?代替
    String sql = "insert into student values(null,?,?,?)";
    // 3. 获得预编译对象
    PreparedStatement ps = conn.prepareStatement(sql);
    // 4. 给占位符赋值
    ps.setString(1, "小泽");
    ps.setString(2, "女");
    ps.setString(3, "1999-10-20");
    // 5. 执行SQL语句
    int row = ps.executeUpdate();
    System.out.println("row = " + row);

    // 5.1 重新给占位符赋值
    ps.setString(1, "小波");
    ps.setString(2, "男");
    ps.setString(3, "2009-09-21");
    row = ps.executeUpdate();
    System.out.println("row = " + row);

    // 5.2 重新给占位符赋值
    ps.setString(1, "小苍");
    ps.setString(2, "女");
    ps.setString(3, "2019-06-21");
    row = ps.executeUpdate();
    System.out.println("row = " + row);

    // 6. 释放资源
    JDBCUtil.close(conn, ps);
}

// 修改数据: 将 id 为 2的用户,姓名更新为 "嫦娥 "  性别换成女,
public  static  void updateStudent() throws Exception {
    // 1. 获得连接对象
    Connection conn = JDBCUtil.getConnection();
    // 2. 准备SQL语句:未知内容使用占位符?代替
    String sql = "update student set name = ?, gender = ? where id = ?";
    // 3. 获得预编译对象
    PreparedStatement ps = conn.prepareStatement(sql);
    // 4. 给占位符赋值
    ps.setString(1, "嫦娥");
    ps.setString(2, "女");
    ps.setInt(3, 2);

    // 5. 执行SQL语句
    int row = ps.executeUpdate();
    System.out.println(row);

    // 6. 释放资源
    JDBCUtil.close(conn, ps);
}

// 删除数据: 删除id为2的学生
public static void deleteStudent() throws Exception {
    // 1. 获得连接对象
    Connection conn = JDBCUtil.getConnection();
    // 2. 准备SQL语句:未知内容使用占位符?代替
    String sql = "delete from student where id = ?";
    // 3. 获得预编译对象
    PreparedStatement ps = conn.prepareStatement(sql);
    // 4. 给占位符赋值
    ps.setInt(1, 2);

    // 5. 执行SQL语句
    int row = ps.executeUpdate();
    System.out.println(row);

    // 6. 释放资源
    JDBCUtil.close(conn, ps);
}

连接池概述

  1. 什么是连接池
    一个负责创建和管理连接对象的容器(集合)

  2. 为什么需要使用连接池
    因为频繁的创建和销毁连接是很耗资源(内存资源和时间资源)的过程。
    使用连接池可以减少频繁创建和效率连接带来的系统开销。 从而提高访问数据库的效率

  3. 连接池的核心思想:连接复用

  4. 连接池规范:DataSource

C3P0连接池基本使用

配置文件模板:c3p0-config.xml
在这里插入图片描述

ComboPooledDataSource构造方法说明
ComboPooledDataSource()使用默认的配置default-config创建数据源对象
ComboPooledDataSource(命名配置)使用命名的配置named-config创建数据源对象

DRUID连接池基本使用

DruidDataSourceFactory类静态方法说明
public static DataSource createDataSource(Properties properties)创建连接池对象

Druid连接池的使用步骤
1. 导入相关jar
2. 准备配置文件:xxx.properties
2.1 配置数据库信息
2.2 配置连接池信息
3. 创建属性集对象:Properties
3.1 加载配置文件信息到属性集对象中
4. 通过Driud提供的工具类方法创建数据源对象
5. 调用数据源对象的方法获得连接对象:getConnection
6. 调用连接对象方法将连接对象关闭返回池中

在这里插入图片描述

连接池工具类

目标:掌握数据源工具类的实现步骤
目的:将创建连接池,获取连接,关闭资源等重复代码封装到工具类中,简化代码编写。

数据源工具类实现步骤

  1. 创建私有静态数据源成员变量 DataSource ds
  2. 在静态代码块中创建连接池
    a) 创建属性集对象
    b) 从类路径下加载属性文件,得到输入流对象
    c) 通过工厂类创建一个数据源
  3. 创建公有的得到数据源的方法 getDataSource()
  4. 创建得到连接对象的方法 getConnection()
  5. 创建释放资源的方法 close(Connction conn, Statement stmt, ResultSet rs)

public class DataSourceUtil {

//  1)	创建私有静态数据源成员变量 DataSource ds
private static DataSource ds = null;


// 2)	在静态代码块中创建连接池:只需要创建1个
static {
   try{
       // a)	创建属性集对象
       Properties info = new Properties();
       // b)	从类路径下加载属性文件,得到输入流对象
       info.load(Demo01.class.getResourceAsStream("/druid.properties"));
       // c)	通过工厂类创建一个数据源
       ds = DruidDataSourceFactory.createDataSource(info);
   } catch(Exception e){
       e.printStackTrace();
   }
}

// 3)	创建公有的得到数据源的方法 getDataSource()
public static DataSource getDataSource(){
    return ds;
}

// 4)	创建得到连接对象的方法 getConnection()
public static Connection getConnection() {
    try{
        return ds.getConnection();
    } catch(Exception e){
        // 将编译时异常包装成运行时异常
        throw new RuntimeException(e);
    }
}

// 5. 定义关闭资源的方法:close(Connection conn, Statement stmt, ResultSet rs)
public static void close(Connection conn, Statement stmt, ResultSet rs){
    /**
     关闭资源注意事项:先开后关(先创建的后关闭)
     1. 创建顺序:Connection ==> Statement ==> ResultSet
     2. 关闭顺序:ResultSet ==> Statement ==> Connectio
     */
    if (rs != null) {
        try {
            rs.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    if (stmt != null){
        try {
            stmt.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    if (conn !=null) {
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

//  重载关闭方法:close(Connection conn, Statement stmt)
public static void close(Connection conn, Statement stmt){
    close(conn, stmt, null);
}

}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值