如何使用JDBC操作数据库?一文带你吃透JDBC规范(二)

本文涉及的产品
对象存储 OSS,20GB 3个月
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
简介: 如何使用JDBC操作数据库?一文带你吃透JDBC规范(二)

5. 数据库连接池


5.1 概念


前面在 JDBC API 详解中,获取的数据库连接对象 conn,在使用时创建,使用完毕就会将其销毁。这样重复创建和销毁的过程实际上是消耗性能和时间的,当大量用户访问数据库时,每次都要进行数据库连接对象的创建和销毁,对系统来说是一种大量的消耗。那么我们怎样来提升性能和节省时间呢?


2.1.png


我们使用数据库连接池来重复利用数据库的连接对象,即 Connection 类对象。


2.2.png


数据库连接池是一个负责分配,管理数据库连接对象的容器,它允许应用程序重复使用同一个数据库连接对象。数据库连接池可以释放空闲时间超过最大空闲时间的数据库连接对象来避免因为没有释放数据库连接对象而引起的数据库连接遗漏。


2.3.png


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


总结来说使用数据库连接池有以下几点好处:


  • 实现资源重用
  • 提升系统响应速度
  • 避免数据库连接遗漏


5.2 实现


sun 公司提供了数据库连接池的标准接口 DataSource ,我们一般使用第三方实现该接口的实现类,所有实现类都继承了其获取连接的方法:


Connection getConnection()


常见的数据库连接池有:


  • Druid(德鲁伊)
  • C3P0
  • DBCP


使用了数据库连接池以后,在获取数据库连接对象时不需要通过 DriverManager类的 getConnection() 方法,而是直接从数据库连接池中获取。我们今天要使用的是 Druid 连接池,它是阿里巴巴开源的数据库连接池项目,其功能强大,性能优秀,使用占比高,是一款优秀的数据库连接池。


6. Druid 连接池的使用


下面以 Druid 连接池为例,讲解通过数据库连接池获取数据库连接对象,主要有以下几个步骤:


1.导入Druid 连接池的 jar 包

2.定义配置文件

3.加载配置文件

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

5.获取连接


第一步:将 Druid 的 jar 包放入项目中的 Lib 目录下作为库文件,jar 包自行下载。


2.4.png


选择 Add as Library,选择模块下有效:


2.5.png


第二步:编写配置文件,在 src 目录下创建文件 druid.properties 。


driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true
username=root
password=1234
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 最大等待时间
maxWait=3000


Druid 配置文件中有很很多的参数,这里配置了用到的几项,其中有连接数据库的名称和密码,初始连接数,最大连接数,最大等待时间等,超过了最大等待时间配置文件还没有加载成功的话,程序就会报错。


第三步:在代码中加载配置文件


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


第四步:在代码中获取连接池对象


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


第五步:获取数据库连接对象


//5. 获取数据库连接 Connection
Connection connection = dataSource.getConnection();
System.out.println(connection); //获取到了连接后就可以继续做其他操作了


示例,Druid的使用完整代码:


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 connection = dataSource.getConnection();
        System.out.println(connection); //获取到了连接后就可以继续做其他操作了  
    }
}


运行结果:


2.6.png


其中,DruidDataSourceFactory 类中的 createDataSource() 方法既可以传入一个 Map 集合,也可以传入 prop 对象,其中都存放配置信息,用来获取连接池对象。


小tips:如果代码中文件的相对路径报错,可以使用 System.getProperty("user.dir") 获取项目的当前路径。

7. 准备工作


前面我们说过,在 Java 代码中,执行 sql 查询语句以后返回一个 ResultSet 类的对象,并且 ResultSet 类提供了方法让我们可以操作查询结果数据,例如可以直接打印所有查询的数据。


示例:


public class JDBCDemo {
    public static void main(String[] args) throws Exception {
        //1. 注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2. 获取连接
        String url="jdbc:mysql://localhost:3306/blog?useSSL=false";
        String username="root";
        String ppassword="abc123";//密码
        Connection conn = DriverManager.getConnection(url,username,password);
        //3. 定义sql
        String sql="select * from student";
        //4. 获取sql执行对象
        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);
            String gender=rs.getString(3);
            System.out.println(id);
            System.out.println(name);
            System.out.println(gender);
            System.out.println("---------");
        }
        //7. 释放资源
        rs.close();
        stmt.close();
        conn.close();
    }
}


运行结果:


2.7.png


显然这样并不是我们想要的效果,数据零散不好处理。所以我们可以把每条数据封装为一个实体类的对象,每个对象对应数据库表的一条记录,并且把每个对象放到集合中存储。练习使用的数据库表:


drop table if exists student;
create table student(
  id int primary key auto_increment,
  name varchar(10),
  gender char(1)
);
insert into student(name,gender) values
('张三','男'),
('李四','女'),
('王五','男');


在 Navicat 中查看数据表:


2.8.png


8. 实战案例


查询学生信息表数据,封装为 Student 类对象,并存放在 ArrayList 集合中。


思路:要解决这个问题,大概分为以下几个步骤:


  • 创建一个 Student 实体类
  • 查询数据库中的数据,并且赋值给对象的属性
  • 将对象存储到 ArrayList 集合中


第一步:创建一个Student 实体类,并定义 set() 方法,重写 Object 类中的 toString 方法,方便查看打印效果。


public class Student {
    private int id;
    private String name;
    private String gender;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                '}';
    }
}


小tips :在 idea 中使用 Alt + Inset 快捷键可以快速给类添加或重写一些方法,例如 get() ,set() ,toString() 方法等。使用 Ctrl + 鼠标左键可以快速选择多项方法。


第二步:使用 Java 代码操作数据库,查询数据库表中所有学生信息并通过 set() 方法赋值给 Student 类的对象,将对象存储到集合中。


public class JDBCDemo {
    public static void main(String[] args) throws Exception {
        //1. 注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2. 获取连接
        String url = "jdbc:mysql://localhost:3306/blog?useSSL=false";
        String username = "root";
        String ppassword = "abc123";//密码
        Connection conn = DriverManager.getConnection(url, username, password);
        //3. 定义sql
        String sql = "select * from student";
        //4. 获取sql执行对象
        Statement stmt = conn.createStatement();
        //5. 执行sql
        ResultSet rs = stmt.executeQuery(sql);
        //6. 处理结果
        List<Student> students = new ArrayList<>();
        while (rs.next()) {
            Student s = new Student();
            int id = rs.getInt(1);
            String name = rs.getString(2);
            String gender = rs.getString(3);
            s.setId(id);
            s.setName(name);
            s.setGender(gender);
            students.add(s);
        }
        System.out.println(students);
        //7. 释放资源
        rs.close();
        stmt.close();
        conn.close();
    }
}


运行结果:


public class JDBCDemo {
    public static void main(String[] args) throws Exception {
        //1. 注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2. 获取连接
        String url = "jdbc:mysql://localhost:3306/blog?useSSL=false";
        String username = "root";
        String ppassword = "abc123";//密码
        Connection conn = DriverManager.getConnection(url, username, password);
        //3. 定义sql
        String sql = "select * from student";
        //4. 获取sql执行对象
        Statement stmt = conn.createStatement();
        //5. 执行sql
        ResultSet rs = stmt.executeQuery(sql);
        //6. 处理结果
        List<Student> students = new ArrayList<>();
        while (rs.next()) {
            Student s = new Student();
            int id = rs.getInt(1);
            String name = rs.getString(2);
            String gender = rs.getString(3);
            s.setId(id);
            s.setName(name);
            s.setGender(gender);
            students.add(s);
        }
        System.out.println(students);
        //7. 释放资源
        rs.close();
        stmt.close();
        conn.close();
    }
}


这样,我们的程序就达到了预期的效果,将来需要使用的数据全部封装为对象并存放在了集合中。


9. 增删改查操作练习


在数据库连接池入门篇中,我们学习了 Druid 连接池的使用,数据库连接池允许重复使用一个现有的数据库连接对象,提升了系统的响应速度和时间。下面我们使用数据库连接池来练习解决上面的问题,并且在获取 sql 执行对象时,我们使用 PreparedStatement 类,解决sql 注入的问题。


9.1 查询所有


查询所有数据,并把查询结果数据封装为对象存储在集合中,这里的数据表,Student 实体类和上面例子中相同。


public class DruidDemo {
    public static void main(String[] args) throws Exception {
        //加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));
        //获取数据库连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
        //获取数据库连接对象
        Connection conn = dataSource.getConnection();
        //定义sql
        String sql = "select * from student";
        //获取 sql 执行对象
        PreparedStatement pstmt = conn.prepareStatement(sql);
        //执行 sql
        ResultSet rs = pstmt.executeQuery();
        //处理数据,将查询结果数据封装为对象存储在集合中
        List<Student> students = new ArrayList<>();
        while (rs.next()) {
            Student s = new Student();
            int id = rs.getInt(1);
            String name = rs.getString(2);
            String gender = rs.getString(3);
            s.setId(id);
            s.setName(name);
            s.setGender(gender);
            students.add(s);
        }
        System.out.println(students);
        //释放资源
        rs.close();
        pstmt.close();
        conn.close();
    }
}


9.2 添加数据


现在演示往数据库中添加一条记录,应用场景为用户在客户端输入一条数据时,我们需要将数据添加到数据库。示例:


public class DruidDemo {
    public static void main(String[] args) throws Exception {
        //接收到用户的数据
        int id=4;
        String name="小美";
        String gender="女";
        //加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));
        //获取数据库连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
        //获取数据库连接对象
        Connection conn = dataSource.getConnection();
        //定义sql
        String sql = "insert into student values(?,?,?)";
        //获取 sql 执行对象
        PreparedStatement pstmt = conn.prepareStatement(sql);
        //设置参数
        pstmt.setInt(1,id);
        pstmt.setString(2,name);
        pstmt.setString(3,gender);
        //执行 sql
        int count = pstmt.executeUpdate();//返回受影响的行数
        //处理数据
        if(count>0){
            System.out.println("添加成功");
        }else{
            System.out.println("添加失败");
        }
        //释放资源
        pstmt.close();
        conn.close();
    }
}

2.11.png


此时的数据表:


2.12.png


9.3 修改数据


现在数据表中的数据,应用场景为用户在客户端修改数据,对应数据库中的数据也要完成修改。示例:


public class DruidDemo {
    public static void main(String[] args) throws Exception {
        //接收到用户的数据
        int id=1;
        String name="小王";
        String gender="女";
        //加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));
        //获取数据库连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
        //获取数据库连接对象
        Connection conn = dataSource.getConnection();
        //定义sql
        String sql = "update student set name=?,gender=? where id=?";
        //获取 sql 执行对象
        PreparedStatement pstmt = conn.prepareStatement(sql);
        //设置参数
        pstmt.setString(1,name);
        pstmt.setString(2,gender);
        pstmt.setInt(3,id);
        //执行 sql
        int count = pstmt.executeUpdate();//返回受影响的行数
        //处理数据
        if(count>0){
            System.out.println("修改成功");
        }else{
            System.out.println("修改失败");
        }
        //释放资源
        pstmt.close();
        conn.close();
    }
}

2.13.png


此时的数据表:


2.14.png


9.4 删除数据


下面演示删除数据,用户在客户端选择删除某条数据记录时,数据库中的数据也要完成删除操作。示例:


public class DruidDemo {
    public static void main(String[] args) throws Exception {
        //接收到用户的数据
        int id=4;
        //加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));
        //获取数据库连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
        //获取数据库连接对象
        Connection conn = dataSource.getConnection();
        //定义sql
        String sql = "delete from student where id=?";
        //获取 sql 执行对象
        PreparedStatement pstmt = conn.prepareStatement(sql);
        //设置参数
        pstmt.setInt(1,id);
        //执行 sql
        int count = pstmt.executeUpdate();//返回受影响的行数
        //处理数据
        if(count>0){
            System.out.println("删除成功");
        }else{
            System.out.println("删除失败");
        }
        //释放资源
        pstmt.close();
        conn.close();
    }
}

2.15.png


此时的数据表:


2.16.png


10. 总结


学习完这篇文章,你将学会使用 Java 代码操作数据库,包括数据库的连接,创建,数据的增删改查等操作。


JDBC 作为基础性的代码,在开发中其实存在着很多的缺点,所以在开发中并不会直接使用,而一般会使用框架开发,使用框架开发不仅能够提高开发的效率,而且大大提高了代码的规范性。MyBatis 就是一款优秀的持久层框架,专门用来简化 JDBC 开发,后面我们马上会接触到,但是在这之前,一定要先熟练 JDBC 的使用。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
Java 关系型数据库 数据库连接
JDBC:Java与数据库的“黄金搭档”,为何它如此重要?
JDBC:Java与数据库的“黄金搭档”,为何它如此重要?
102 8
|
6月前
|
SQL Java 数据库连接
【YashanDB数据库】由于网络带宽不足导致的jdbc向yashandb插入数据慢
由于网络带宽不足导致的jdbc向yashandb插入数据慢
|
8月前
|
SQL Java 关系型数据库
使用 JDBC 实现 Java 数据库操作
JDBC(Java Database Connectivity)是 Java 提供的数据库访问技术,允许通过 SQL 语句与数据库交互。本文详细介绍了 JDBC 的使用方法,包括环境准备、编程步骤和完整示例。
767 7
|
9月前
|
SQL Java 数据库连接
JDBC编程安装———通过代码操控数据库
本文,教你从0开始学习JBCD,包括驱动包的下载安装调试设置,以及java是如何通过JBDC实现对数据库的操作,以及代码的分析,超级详细
|
11月前
|
SQL Java 数据库
Springboot+spring-boot-starter-data-jdbc实现数据库的操作
本文介绍了如何使用Spring Boot的spring-boot-starter-data-jdbc依赖来操作数据库,包括添加依赖、配置数据库信息和编写基于JdbcTemplate的数据访问代码。
1170 2
|
SQL Java 数据库连接
JDBC之旅:从陌生到熟悉的Java数据库连接之路
JDBC之旅:从陌生到熟悉的Java数据库连接之路
79 9
|
SQL Java 关系型数据库
探索Java数据库连接的奥秘:JDBC技术全攻略
探索Java数据库连接的奥秘:JDBC技术全攻略
151 8
|
SQL Java 数据库连接
Java开发者必知:JDBC连接数据库的“三大法宝”
Java开发者必知:JDBC连接数据库的“三大法宝”
106 7
|
11月前
|
SQL druid Java
JDBC和数据库连接池-两个工具类-JDBCUtilsByDruid和BasicDAO
JDBC和数据库连接池-两个工具类-JDBCUtilsByDruid和BasicDAO
491 0
|
SQL Java 数据库连接
从一名对数据库连接操作一无所知的新手,逐渐成长为能够熟练驾驭JDBC的开发者
在充满代码与逻辑的世界中,我从一名对数据库操作一无所知的新手,逐步成长为熟练掌握JDBC的开发者。这段旅程充满挑战与惊喜,从建立连接到执行SQL语句,再到掌握事务管理和批处理等高级功能,每一步都让我对JDBC有了更深的理解。示例代码展示了如何使用`DriverManager.getConnection()`连接数据库,并利用`PreparedStatement`执行参数化查询,有效防止SQL注入。这段经历不仅提升了我的技术能力,更让我领略到编程之美与解决问题的乐趣。
75 0