Java JDBC

Java JDBC

简介

JDBC全称: Java Data Base Connectivity,Java 数据库连接;

JDBC是Sun公司提供的一套用于数据库操作的接口,Java程序可以通过JDBC接口连接到数据库并执行SQL语句;

JDBC的本质是:官方(sun公司)定义的接口,数据库厂商去实现接口,提供数据库驱动jar包;

我们可以使用JDBC接口编程,真正执行的代码是驱动jar包中的实现类;

JDBC的工作原理示意图如下:
jdbc

JDBC的好处:

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

JDBC连接数据库

JDBC连接数据的细致流程使用步骤:

  1. 读取配置
  2. 加载驱动
  3. 连接数据库
// 1. 读取配置,即获取数据库的连接信息
private static String url = "jdbc:mysql://localhost:3306/yygh_user";
private static String username = "root";
private static String password = "your password";
// 2. 加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 3. 获取连接
Connection connection = DriverManager.getConnection(url, username, password);

JDBC的URL格式:

jdbc_url

JDBC规定url的格式由三部分组成,每个部分中间使用冒号分隔。

  1. 第一部分是jdbc,这是固定的;
  2. 第二部分是数据库名称,那么连接mysql数据库,第二部分当然是mysql了;
  3. 第三部分是由数据库厂商规定的,我们需要了解每个数据库厂商的要求,mysql的第三部分分别由数据库服务器的IP地址(localhost)、端口号(3306),以及DATABASE名称(mydb)组成。

如果连接的是本地的Mysql数据库,并且连接使用的端口是3306,那么的url地址可以简写为:

jdbc: mysql://数据库,
例如:jdbc: mysql://localhost:3306/mydb

导入驱动包
第0步:首要步骤!!

  • 在当前项目根目录下建立一个“lib”文件夹;
  • 把“mysql-connector-java-5.1.18.jar”复制到该文件夹中;
  • 选中该jar包,右键,执行“build Path”才能真正导入该jar包。才可以开始执行以下的步骤!

为什么要导入这个jar包?

  • 因为我们在程序中要使用mysql的驱动,而mysql的驱动在jar包中,所以需要导入jar包;
  • 里面提供了MySQL的实现类:com.mysql.jdbc.Driver;
  • 我们可以在mysql的官网上下载mysql的驱动包,也可以在maven仓库中下载mysql的驱动包。

注册驱动
注册驱动有两种方式:

  • 注册驱动的方式一:使用Class.forName()方法注册驱动;
  • 注册驱动的方式二:使用DriverManager.registerDriver()方法注册驱动;

注意

  • JDBC规范定义驱动接口在java.sql.Driver,也就是你要操作数据库的所有方法都要在这个包下查找。

注册驱动法一:创建驱动对象,直接连接数据库

package com.basic.jdbc;

import com.mysql.jdbc.Driver;
import com.sun.org.slf4j.internal.Logger;
import com.sun.org.slf4j.internal.LoggerFactory;
import lombok.extern.slf4j.Slf4j;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

@Slf4j
public class JdbcMethodOne {
    private static final Logger logger = LoggerFactory.getLogger(JdbcMethodOne.class);

    //数据库连接信息
    private static String url = "jdbc:mysql://localhost:3306/yygh_user";
    private static String username = "root";
    private static String password = "your password";

    private static Connection connect;

    //使用驱动程序链接测试
    public static void main(String[] args){

        try {
            //1.创建驱动程序类对象;
            Driver driver = new Driver();

            //2.设置用户名和密码
            Properties properties = new Properties();
            properties.setProperty("user", username);
            properties.setProperty("password", password);

            //3.连接数据库,返回连接对象
            connect = driver.connect(url, properties);
            System.out.println(connect.toString());

        }catch (SQLException e){
            logger.error(String.valueOf(e));
        }finally {
            try {
                connect.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }



    }
}

不推荐使用这种注册方式:

  • 通过查询驱动包中的Driver类的源码可知:该类的static代码块中已经执行了“DriverManager.registerDriver(driver);”,那么这就相当于注册了两次,也就是在内存中会有两个Driver对象,冗余了

注册驱动法二: 使用驱动管理器类连接数据库

package com.basic.jdbc;

import com.mysql.jdbc.Driver;

import java.sql.DriverManager;
import java.sql.SQLException;

public class JdbcMethodTwo {
    private static String url = "jdbc:mysql://localhost:3306/yygh_user";
    private static String username = "root";
    private static String password = "your password";
    private static Driver driver;
    public static void main(String[] args) throws SQLException {
        try {
            driver = new Driver();
            // 1.注册驱动程序(可以注册多个驱动程序)
            DriverManager.registerDriver(driver);
            //注意,通过查询驱动包中的Driver类的源码可知:该类的static代码块中已经执行了“DriverManager.registerDriver(driver);”,那么这就相当于注册了两次,冗余了
            //2.获取连接
            java.sql.Connection connect = DriverManager.getConnection(url, username, password);
            System.out.println(connect.toString());
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            //Removes the specified driver from the DriverManager's list of registered drivers.
            DriverManager.deregisterDriver(driver);
        }
    }

}

不推荐使用这种注册方式:

  1. 硬编码,后期不易于程序扩展和维护
  2. 通过查询驱动包中的Driver类的源码可知:该类的static代码块中已经执行了“DriverManager.registerDriver(driver);”,那么这就相当于注册了两次,也就是在内存中会有两个Driver对象,冗余了
  3. 程序依赖mysql的api,脱离mysql的jar包,程序将无法编译,将来程序切换底层数据库将会非常麻烦。

注册驱动法三: 使用加载驱动程序类来注册驱动程序

package com.basic.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class JdbcMethodTri {

    private static String url = "jdbc:mysql://47.93.122.157:3306/yygh_user";
    private static String username = "root";
    private static String password = "shart1314";

    private static Connection connection;

    public static void main(String[] args) {
        try {
            // 1.通过得到字节码对象的方式加载静态代码块,从而注册驱动程序
            Class.forName("com.mysql.jdbc.Driver");

            // 2.通过加载驱动程序类连接到具体的数据库
         connection = DriverManager.getConnection(url, username, password);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            // 3.关闭连接
            try {
                connection.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

底层原理:

  • 通常开发我们使用Class.forName() 加载一个使用字符串描述的驱动类。
  • 如果使用Class.forName()将类加载到内存,该类的静态代码将自动执行。
  • 通过查询com.mysql.jdbc.Driver源码,我们发现Driver类“主动”将自己进行注册。
  • 结论:推荐使用

JDBC操作数据库

基本步骤:

  • 加载JDBC驱动程序
  • 建立数据库连接Connection
  • 创建执行SQL的语句Statement
  • 处理执行结果ResultSet/int

前提准备

在 resource 目录新建个配置文件,application.properties:

#value值不要有双引号("")和分号(;)
jdbc.url=jdbc:mysql://xxxx:3306/yygh_user
jdbc.username=root
jdbc.password=xxxxxx

新建个 工具类,主要功能就是获取连接和关闭连接:

package com.basic.jdbc.util;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JDBCUtil {

    public static Connection getConn(){
        Properties properties = new Properties();
        try {
            //使用 JDBCUtil 类的类加载器获取 application.properties 文件的输入流。getResourceAsStream 方法会在类路径下查找指定名称的文件,若找到则返回其输入流。
            InputStream resourceAsStream = JDBCUtil.class.getClassLoader().getResourceAsStream("application.properties");
            // 调用 Properties 对象的 load 方法,将输入流中的属性加载到 properties 对象中。该方法会解析输入流中的键值对,格式通常为 key=value。
            properties.load(resourceAsStream);

            String url = properties.getProperty("jdbc.url");
            String username = properties.getProperty("jdbc.username");
            String password = properties.getProperty("jdbc.password");

            //加载驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //连接数据库
            Connection connection = DriverManager.getConnection(url, username, password);

            return connection;
        } catch (IOException e) {
            System.out.println("未找到配置文件");
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            System.out.println("驱动类无法找到");
            throw new RuntimeException(e);

        } catch (SQLException e) {
            System.out.println("数据库连接失败");
            throw new RuntimeException(e);

        }
    }

    public static void close(Connection connection, Statement statement, ResultSet rs){
        if(rs != null){
            try {
                rs.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }

        if(statement != null){
            try {
                statement.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }

        if(connection != null){
            try {
                connection.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

增-插入操作(insert)

主要演示单条插入和批量插入数据:

package com.basic.jdbc.util;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * @description: 单条插入和批量插入数据
 */
public class SqlInsert {

    public void insert() throws SQLException {
        Connection connection = null;
        //1.获取conn
        connection = JDBCUtil.getConn();
        //2.sql 语句,占位符
        String sql = "INSERT INTO user_login_record (`user_id`,`create_time`,`update_time`,`is_deleted`) VALUES (?, ?, ?, ?)";
        // 3.获取sql语句对象
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //4.填入字段内容
        // 第一个占位符字段,Int类型
        preparedStatement.setInt(1,100);
        // 第二个占位符字段,Date类型
        preparedStatement.setDate(2,new java.sql.Date(System.currentTimeMillis()));
        // 第二个占位符字段,Date类型
        preparedStatement.setDate(3,new java.sql.Date(System.currentTimeMillis()));
        // 第四个占位符字段,Int类型
        preparedStatement.setInt(4,0);
        //5,执行sql
        preparedStatement.executeUpdate();

        JDBCUtil.close(connection,preparedStatement,null);
    }

    public void insertBatch() throws SQLException {
        Connection connection = null;
        connection = JDBCUtil.getConn();
        //关闭自动提交
        connection.setAutoCommit(false);

        String sql = "INSERT INTO user_login_record (`user_id`,`create_time`,`update_time`,`is_deleted`) VALUES (?, ?, ?, ?)";

        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        for (int i = 0; i < 10; i++) {
            preparedStatement.setInt(1,100+i);
            preparedStatement.setDate(2,new java.sql.Date(System.currentTimeMillis()));
            preparedStatement.setDate(3,new java.sql.Date(System.currentTimeMillis()));
            preparedStatement.setInt(4,0);
            preparedStatement.addBatch();
        }
        preparedStatement.executeBatch();
        //开始提交执行
        connection.commit();

        //手动执行关闭(也可以调用JDBCUtil.close()方法)
        preparedStatement.close();
        connection.close();
    }

}

删-按条件删除记录行(delete)

package com.basic.jdbc.util;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class SqlDelete {
    public void delete() throws SQLException {
        Connection connection = null;
        connection = JDBCUtil.getConn();

        String sql = "DELETE FROM user_login_record WHERE id=?";

        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setInt(1,121);

        int i = preparedStatement.executeUpdate();

        if (i==0){
            System.out.println("执行失败!");
        }else {
            System.out.println("执行成功!");
        }

        JDBCUtil.close(connection,preparedStatement,null);
    }
}

改-更新数据(update)

按照条件更新记录行:

package com.basic.jdbc.util;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * @Title: SqlUpdate
 * @Author Joudys
 * @Package com.basic.jdbc.util
 * @date: 2025/6/29 14:36
 * @description: TODO
 */
public class SqlUpdate {
    public void update() throws SQLException {
        Connection conn = null;
        conn = JDBCUtil.getConn();

        //String sql = "UPDATE user_login_record SET user_id=?,create_time=?,update_time=?,is_deleted=? WHERE id=?";
        String sql = "UPDATE user_login_record SET user_id=? WHERE id=?";

        PreparedStatement preparedStatement = conn.prepareStatement(sql);

        preparedStatement.setInt(1,200);
        //preparedStatement.setDate(2, new Date(System.currentTimeMillis()));
        //preparedStatement.setDate(3, new Date(System.currentTimeMillis()));
        //preparedStatement.setInt(4,1);
        preparedStatement.setInt(2,122);

        int result = preparedStatement.executeUpdate();
        System.out.println("影响行数:"+result);

        JDBCUtil.close(conn,preparedStatement,null);
    }
}

查-查询数据(select)

这里简单获取所有数据,或者按照条件查询数据:

package com.basic.jdbc.util;

import java.sql.*;

public class SqlSelect {
    public void queryAll() throws SQLException {
        Connection conn = null;
        conn = JDBCUtil.getConn();

        String sql = "SELECT * FROM user_login_record";

        PreparedStatement statement = conn.prepareStatement(sql);
        //执行查询语句
        ResultSet resultSet = statement.executeQuery();
        //处理结果,多条解=结果用while,单条用if
        while(resultSet.next()){
            // 通过字段名获取对象值
            int id = resultSet.getInt("id");
            int userId = resultSet.getInt("user_id");
            String ip = resultSet.getString("ip");
            Date createTime = resultSet.getDate("create_time");
            Date updateTime = resultSet.getDate("update_time");
            int isDeleted = resultSet.getInt("is_deleted");
            System.out.println(String.format("`id`=%d,`user_id`=%d,`ip`=%s,`create_time`=%s,`update_time`=%s,`is_deleted`=%d",
                    id,userId,ip,createTime.toString(),updateTime.toString(),isDeleted));

        }
        JDBCUtil.close(conn,statement,resultSet);
    }

    public void queryById(int id) throws SQLException {
        Connection conn = null;
        conn = JDBCUtil.getConn();

        String sql = "SELECT * FROM user_login_record WHERE id=?";

        PreparedStatement statement = conn.prepareStatement(sql);

        statement.setInt(1,id);
        //执行查询语句
        ResultSet resultSet = statement.executeQuery();
        //处理结果,多条解=结果用while,单条用if
        if(resultSet.next()){
            // 通过字段名获取对象值
            int tableId = resultSet.getInt("id");
            int userId = resultSet.getInt("user_id");
            String ip = resultSet.getString("ip");
            Date createTime = resultSet.getDate("create_time");
            Date updateTime = resultSet.getDate("update_time");
            int isDeleted = resultSet.getInt("is_deleted");
            System.out.println(String.format("`id`=%d,`user_id`=%d,`ip`=%s,`create_time`=%s,`update_time`=%s,`is_deleted`=%d",
                    tableId,userId,ip,createTime.toString(),updateTime.toString(),isDeleted));
        }
        JDBCUtil.close(conn,statement,resultSet);
    }
}

事务处理

事务处理,先开启事务,关闭自动提交,然后执行语句,提交,执行有问题则回滚事务:

package com.basic.jdbc.util;

import java.sql.*;

public class SqlTransaction {
    public void transactionInsert(int queryId) throws SQLException {
        Connection conn = null;
        PreparedStatement statement = null;
        conn = JDBCUtil.getConn();
        try{
            //开启事务
            conn.setAutoCommit(false);

            String sql = "SELECT * FROM user_login_record WHERE id=?";
            statement = conn.prepareStatement(sql);
            statement.setInt(1,queryId);

            ResultSet resultSet = statement.executeQuery();

            //提交事务
            conn.commit();
            if(resultSet.next()){
                // 通过字段名获取对象值
                int id = resultSet.getInt("id");
                int userId = resultSet.getInt("user_id");
                String ip = resultSet.getString("ip");
                Date createTime = resultSet.getDate("create_time");
                Date updateTime = resultSet.getDate("update_time");
                int isDeleted = resultSet.getInt("is_deleted");
                System.out.println(String.format("`id`=%d,`user_id`=%d,`ip`=%s,`create_time`=%s,`update_time`=%s,`is_deleted`=%d",
                        id,userId,ip,createTime.toString(),updateTime.toString(),isDeleted));
            }
            resultSet.close();
        } catch (SQLException e) {
            e.printStackTrace();
            //回滚事务
            conn.rollback();
        }
        JDBCUtil.close(conn,statement,null);
    }
    public void transactionUpdate() throws SQLException {
        Connection conn = null;
        PreparedStatement statement = null;
        conn = JDBCUtil.getConn();


        try {
            //关闭自动提交,开启事务
            conn.setAutoCommit(false);

            String sql = "UPDATE user_login_record SET user_id=?,is_deleted=? WHERE id=?";

            statement = conn.prepareStatement(sql);

            statement.setInt(1,300);
            statement.setInt(2,0);
            statement.setInt(3,122);

            statement.executeUpdate();
            //2.提交事务
            conn.commit();
        } catch (SQLException e) {
            e.printStackTrace();
            //3.回滚事务
            conn.rollback();
        }finally {
            statement.close();
            conn.close();
        }
    }
}

方法介绍

重要类、接口、方法:

  • Statement :接口,主要声明执行语句和结果获取,在我们进行 DDL 操作的时候,可以通过 Connection.createStatement() 获取再操作。

  • preparestatement :是 Connection 类 的方法,通过调用此方法,传入提前定义好的 sql 语句,返回 PrepareStatement 接口的对象,同样也可以去调用 executeQuery/executeUpdate 去执行静态语句。

  • callablestatement: 继承自PreparedStatement接口,用于调用存储过程。

  • boolean execute():在 PrepareStatement 语句中使用,效果等同于 executeQuery/executeUpdate,但有一点需要注意,如是是查询语句,执行后要返回 true/false,如果要获取查询的结果,应该再次调用 Statement.getResultSet,如果是 update 类的语句,则可以调用 Statement.getUpdateCount。

  • ResultSet executeQuery():执行了 SQL DQL 查询语句后,返回查询的结果集。

  • int executeUpdate :执行 DML 后,返回整型值,可以是影响行数,或者0,主要针对 INSERT、UPDATE、DELETE 语句。

  • void addBatch():在如执行批量插入操作时,将一组参数加入到 PrepareStatement 中。

  • int[] executeBatch():提交批量操作的命令,正式执行批量操作。

  • setSomeType():主要针对 PrepareStatement 对象,对占位符的参数进行设置,占位符的序号+字段值。

参考链接:

  1. JDBC的基本使用步骤
  2. JDBC介绍
posted @ 2025-06-30 21:53  joudys  阅读(36)  评论(0)    收藏  举报