JDBC 数据库连接技术简介

更新时间:2019-11-08 10:01:59点击次数:293次
1. JDBC 概念
JDBC(Java DataBase Connectivity,Java数据库连接),是一种用于执行 SQL 语句的 Java API ,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC 提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序,同时,JDBC也是个商标名。

JDBC 百度百科

概念解释:

定义了一套操作所有关系型数据库的规则(接口)。
不同的 JDBC 实现类由不同的厂商实现(数据库驱动),提供驱动数据库的 jar 包。
我们可以使用这套 JDBC 编程,正真执行的代码是驱动 jar 包中的实现类。
2. 快速入门
2.1 建表
首先在MySQL数据库中准备一个表供后续的所有操作。

-- 创建用户账单表
create table account(
  id INT PRIMARY KEY AUTO_INCREMENT,
  a_name VARCHAR(30),
  a_money DOUBLE
);
-- 添加张三、李四的账户
insert into account(id,a_name,a_money) values
(1,"张三",1000),
(2,"李四",1000);

2.2 代码展示
需要提前导入连接数据库的包,如果没有,参考这篇教程 MySQL驱动下载。

我这里用的是 MySQL8.0.17 版本,根据自己数据库的安装版本下载对应的驱动。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
/**
 * JDBC快速入门
 * 实现,转账操作
 */
public class JdbcDemo {
    public static void main(String[] args) throws Exception{
        //1. 导入jar包
        //2. 注册驱动:5.0版本后可以省略这一步书写
        Class.forName("com.mysql.cj.jdbc.Driver");
        //3. 获取数据库连接对象:
        //若连接本地默认3306端口数据库可以简写为jdbc:mysql:///数据库名?serverTimezone=UTC
        Connection conn =  DriverManager.getConnection("jdbc:mysql://localhost:3306/demo_test?serverTimezone=UTC","root","root");
        //4. 定义sql
        String sql1 = "update account set a_money = 500 where id = 1";
        String sql2 = "update account set a_money = 1500 where id = 1";
        //5. 获取sql的对象 Statement
        Statement stmt = conn.createStatement();
        //6. 执行sql
        int count = stmt.executeUpdate(sql1);
        int count2 = stmt.executeUpdate(sql2);
        //7. 查看处理结果
        System.out.println(count);
        System.out.println(count2);
        //8. 释放资源
        stmt.close();
        conn.close();
    }
}

注意:

mysql 5.0 注册驱动:com.mysql.jdbc.Driver
mysql 5.0 连接数据库:jdbc:mysql://localhost:3306/demo_test
mysql 8.0 注册驱动:com.mysql.cj.jdbc.Driver
mysql 8.0 连接数据库:dbc:mysql://localhost:3306/demo_test?serverTimezone=UTC
3. JDBC 中各个对象
(Java.sql 的 API 介绍)

这里简单介绍几个常用管理对象,具体参照 API 中的介绍。

对象 功能 API介绍
DriverManager 与驱动程序建立连接 DriverManager 的API介绍
Connection 提供创建语句以及管理连接及其属性的方法 Connection 的API介绍
Statement 执行sql的对象,用于发送基本的SQL语句。 Statement 的API介绍
PreparedStatement 执行sql对象,用于发送准备好的语句或基本的SQL语句 PreparedStatement 的API介绍
ResultSet 检索和更新查询结果 ResultSet 的API介绍
3.1 DriverManager
用于管理一组JDBC驱动程序的基本服务。

方法 描述
static Connection getConnection(String url, String user, String password) 尝试建立到给定数据库URL的连接。
参数解释:

url:指定连接的路径:jdbc:mysql://ip地址(域名):端口号/数据库名称
如果连接的是本机 MySQL 服务器,并且 MySQL 服务器默认端口是 3306,则 url 可以简写为:jdbc:mysql:///数据库名称 。
user:数据库连接用户名
password:数据库连接密码
代码应用片段:

Connection conn =  DriverManager.getConnection("jdbc:mysql://localhost:3306/demo_test?serverTimezone=UTC","root","root");

3.2 Connection
与特定数据库的连接(会话)。执行SQL语句,并在连接的上下文中返回结果。

方法 描述
Statement createStatement() 创建一个Statement对象,用于将SQL语句发送到数据库。
PreparedStatement prepareStatement(String sql) 创建一个PreparedStatement对象,用于将参数化的SQL语句发送到数据库
void setAutoCommit(boolean autoCommit) 将此连接的自动提交模式设置为给定状态。
void commit() 使自上一次提交/回滚以来的所有更改永久生效,并释放此Connection对象当前持有的所有数据库锁。
void rollback() 撤消在当前事务中进行的所有更改,并释放此Connection对象当前持有的所有数据库锁。
代码应用片段:

Statement stmt = conn.createStatement();
int count = stmt.executeUpdate(sql);

3.3 Statement
用于执行静态SQL语句并返回其产生的结果的对象。

方法 描述
boolean execute(String sql) 执行任意给定的SQL语句,该语句可能返回多个结果。
int executeUpdate(String sql) 执行DML(insert、update、delete)返回改变行数,或者执行DDL(create、alter、drop)不返回任何内容。
ResultSet executeQuery(String sql) 执行给定的SQL语句,该语句返回一个 ResultSet对象。
代码应用片段:

Statement stmt = null;
int count = stmt.executeUpdate(sql);
int count = stmt.executeUpdate(sql);
ResultSet rs = stmt.executeQuery(sql);

3.4 PreparedStatement
表示预编译的 SQL 语句的对象,SQL 语句已预编译并存储在 PreparedStatement 对象中。然后可以使用该对象多次有效地执行该语句。预编译 SQL 时,参数用占位符(?)占位,等应用时再用实际参数替换占位符(?)。

方法 描述
PreparedStatement Connection.prepareStatement(String sql) 创建一个 PreparedStatement对象,用于将参数化的SQL语句发送到数据库。
setXXX(参数1,参数2) 给预编译SQL语句中的占位符 ? 赋值
注意:

Xxx 可以为任意基本类型,与数据库中一致。
参数1:占位符(?)的位置,从1开始计数
参数2:占位符(?)的替换值
代码应用片段:

//定义预编译 SQL 语句,具体参数用占位符(?)代替
String sql1 = "update account set a_money = a_money - ? where id = ?";
String sql2 = "update account set a_money = a_money + ? where id = ?";
//预编译sql对象
PreparedStatement pstmt1 = conn.prepareStatement(sql1);
PreparedStatement pstmt2 = conn.prepareStatement(sql2);
//设置参数
pstmt1.setDouble(1,500);
pstmt1.setInt(2,1);
pstmt2.setDouble(1,500);
pstmt2.setInt(2,2);

3.5 ResultSet
代表数据库结果集的数据表,通常通过执行查询数据库的语句来生成。

方法 描述
boolean next() 向后移动游标,判断当前行是否有记录,有则返回 true,反之返回false
getXxx() 获取Xxx类型的数据
关于getXxx()方法的注意事项:

Xxx为基本数据类型,如:getString()、getInt()等。
参数可以是列的编号或者是列的名称。
代码应用片段

while(resultset.next()){
    int id = resultset.getInt(1);
    String name = resultset.getString("a_name");
    double money = resultset.getDouble(3);
    System.out.println(id + "---" + name + "---" + money);
}

4. 抽取 JDBC 的工具类
4.1 目的

简化代码编写,增加代码的可维护性,将 JDBC 的基本操作放到一个工具类中,用配置文件来获取连接信息,降低耦合。

4.2 操作

在一个类中完成注册驱动、获取连接、释放资源等 JDBC 相关操作,抽取一个方法获取连接对象,用配置文件(jdbc.properties)的方式保存连接信息,让工具类具有通用性。

4.3 配置文件的编写

url=jdbc:mysql:///demo_test?serverTimezone=UTC
user=root
password=root
driver=com.mysql.cj.jdbc.Driver

4.4 工具类的编写

import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;

/**
 * JDBC工具类
 */
public class JdbcUtils {
    //声明成员变量,只有静态变量才能被静态方法访问。
    private static String url;
    private static String user;
    private static String password;
    private static String driver;
    /**
     * 文件的读取,只需要读取一次即可拿到这些值,使用静态代码块
     */
    static {
        //读取资源文件,获取值。
        try {
            //1. 创建Properties集合类
            Properties pro = new Properties();
            //获取src路径下的文件的方法————》类加载器 ClassLoader
            ClassLoader classLoader = JdbcUtils.class.getClassLoader();
            URL res = classLoader.getResource("jdbc.properties");
            String path = res.getPath();
            System.out.println(path);
            //2. 加载文件
            pro.load(new FileReader(path));
            //3. 获取数据,赋值
            url = pro.getProperty("url");
            user = pro.getProperty("user");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");
            //4. 注册驱动
            Class.forName(driver);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    /**
     * 获取连接的对象
     * @return 连接对象
     */
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url,user, password);
    }
    /**
     * 释放资源
     * @param stmt
     * @param conn
     */
    public static void  close(Statement stmt, Connection conn){
        if (stmt != null){
            try {
                stmt.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        if (conn != null){
            try {
                conn.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
    }
    /**
     * 释放资源重载
     * @param rs
     * @param stmt
     * @param conn
     */
    public static void  close(ResultSet rs, Statement stmt, Connection conn){
        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. 综合实例
案例需求:完成张三和李四的转账操作,张三账户 -500 ,李四账户 +500

创建数据库
-- 创建用户账单表
create table account(
  id INT PRIMARY KEY AUTO_INCREMENT,
  a_name varchar(30),
  a_money double
);

-- 添加张三、李四的账户
insert into account(id,a_name,a_money) values
(1,"张三",1000),
(2,"李四",1000);

-- 查询表
select * from account;

编写 jdbc.properties 配置文件,放在src目录下。内如参照 JDBC工具类抽取。

编写工具类,内容参照 JDBC 工具类抽取。

编写主类

package base.jdbc;

import base.util.JdbcUtils;
import java.sql.*;
/**
 * 转账操作
 */
public class JdbcDemo8 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt1 = null;
        PreparedStatement pstmt2 = null;
        try {
            //1.获取连接
            conn = JdbcUtils.getConnection();
            //开启事务管理
            conn.setAutoCommit(false);//值为false开启
            //2.定义sql
            //2.1 张三 - 500
            String sql1 = "update account set a_money = a_money - ? where id = ?";
            //2.2 李四 + 500
            String sql2 = "update account set a_money = a_money + ? where id = ?";
            //3. 获取执行sql对象,预编译,参数用 ? 占位符
            pstmt1 = conn.prepareStatement(sql1);
            pstmt2 = conn.prepareStatement(sql2);
            //4.设置参数占位符的参数
            pstmt1.setDouble(1,500);
            pstmt1.setInt(2,1);
            pstmt2.setDouble(1,500);
            pstmt2.setInt(2,2);
            //5.执行sql
            pstmt1.executeUpdate();
            pstmt2.executeUpdate();
            //提交改变
            conn.commit();
        } catch (Exception e) {
            try{
                if (conn != null) {
                    conn.rollback();
                }
            } catch (SQLException se){
                se.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            JdbcUtils.close(pstmt1,conn);
            JdbcUtils.close(pstmt2,null);
        }
    }
}

再次查询表中内容
select * from account;

本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是一个个人学习交流的平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽,造成漏登,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

  • 项目经理 点击这里给我发消息
  • 项目经理 点击这里给我发消息
  • 项目经理 点击这里给我发消息
  • 项目经理 点击这里给我发消息