JDBC-一套操作数据库的api

介绍

JDBC就是另外一种操作数据库的方式

JDBC:Java DataBase Connectivity

Mysql提供了驱动包

驱动包:就是MYSQL厂商提供了一套JDBC规范的实现。

jdbc包含四个对象

  1. DriverManager: 驱动管理类
  2. Connection接口:连接对象
  3. Statement接口:执行sql语句
  4. ResultSet接口:处理查询后的结果集

步骤

手动导入
idea导入类库版本
  1. 打开项目结构(Project Structure)

选择Libraries 添加 java

选择对应的路径

JDBC步骤【重要】

准备数据

sql 复制代码
create table tb_user (
	id int(11) primary key auto_increment comment "用户列表",
	username varchar(30) comment "用户名",
	password varchar(30) comment "密码",
	phone varchar(11) comment "手机号",
	createTime date comment "注册时间",
	money double(10,2) comment "帐户余额",
	sex int(1) comment "性别 0女1男"
	);
标准步骤
  1. 加载驱动 :通过DriverManager注册数据库驱动
  2. 建立连接 :使用DriverManager.getConnection()获取Connection对象
  3. 创建Statement :通过Connection创建SQL执行对象
  4. 执行SQL :使用Statement执行SQL语句
  5. 处理结果 :通过ResultSet处理查询结果
  6. 关闭资源 :按ResultSet → Statement → Connection顺序关闭资源

jdbc:mysql://127.0.01:3306/数据库名?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai ;

java 复制代码
public class Demo_insert {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {

        // 1 . 加载驱动
        // ps:利用反射技术,将驱动类加载到JVM
        Class.forName("com.mysql.cj.jdbc.Driver") ;

        // 2 . 通过驱动管理对象获取连接对象
        // jdbc:mysql:是协议 固定写法
        // localhost:3306 域名
        // java2023 是库名
        String url = "jdbc:mysql://localhost:3306/java2023";
        String username = "root";
        String password = "root";
        Connection connection = DriverManager.getConnection(url, username, password);

        // 3 . 获得执行sql语句的对象
        Statement statement = connection.createStatement();

        // 4 . 通过执行语句对象, 执行sql,获取结果
        String sql = "insert into tb_user (id,username,password,phone,createTime,money,sex) VALUES (2, \"小罗\",\"123456\",\"17783466057\",\"2023-07-02\",2000.0,1);";
        // 执行查询 是 executeQuery()
        // 执行增删改 是 executeUpdate()
        int i = statement.executeUpdate(sql);
        if(i > 0) {
            System.out.println("插入成功");
        }
        // 5 . 关流
        statement.close();
        connection.close();
    }
}

获取添加最后一个数据的id

select last_insert_id(); -- 获取最后一个添加的id,前提是添加数据时不能指定id

查询结果集ResultSet【重要】

查询返回的是一种虚拟表,Java的JDBC中是使用结果集(ResultSet)来封装这个虚拟表,结果集就是一个集合

java 复制代码
public class Demo_ResultSet {

    public static void main(String[] args) throws ClassNotFoundException, SQLException {

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

        String url = "jdbc:mysql://localhost:3306/java2023?useSSL=false";
        String username = "root";
        String password = "root";
        Connection connection = DriverManager.getConnection(url,username,password);

        Statement statement = connection.createStatement();

        String sql = "SELECT  * FROM tb_user ; ";

        ResultSet resultSet = statement.executeQuery(sql);

        // resultSet.next()
   /*     if (resultSet.next()) {
            int anInt = resultSet.getInt(1);
            String userStr = resultSet.getString(2);
             System.out.println(userStr);
            System.out.println(anInt);
        }*/

        while (resultSet.next()) {
            String username1 = resultSet.getString("username");
            System.out.println(username1);
        }

        statement.close();
        connection.close();
    }
}

PreparedStatement批量添加

sql 复制代码
create table category(
  cid int primary key auto_increment ,
  cname varchar(10)
);
  1. 注意:
    1. mysql默认情况下不会批量添加, 添加的时候都是一条一条添加的,这里的批量添加其实就是将多个要添加的数据先打包到内存,然后再将打包好的数据一起添加到数据库中,这里效率会提高
    2. 由于mysql默认情况下不会批量添加,所以我们想要进行批量添加的操作,需要手动开启功能
      1. jdbc:mysql://localhost:3306/msb_test01?rewriteBatchedStatements=true
  2. 批量添加方法: 用到PreparedStatement中的方法
    1. void addBatch() -> 将一组数据保存起来,给数据打包,放到内存中
    2. executeBatch() -> 将打包好的数据一起发给mysql

jdbc.properties文件:

properties 复制代码
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/msb_test01?rewriteBatchedStatements=true
user=root
pwd=root
java 复制代码
static void main() throws SQLException {
Connection connection = JDBCUtils.getConnection();
String sql = "insert into category(cname) values (?)";

PreparedStatement pds = connection.prepareStatement(sql);

for (int i = 0; i < 100; i++) {
    pds.setObject(1,"xiaobo" + i);
    // 将数据一起添加到内存中
    pds.addBatch();
}
// 执行sql:将内存中的数据一起发送给mysql
int[] ints = pds.executeBatch();
JDBCUtils.close(connection,pds,null);
}

连接池

  1. 问题描述:
    1. 我们之前每个操作都需要先获取一条新的连接对象,用完之后就需要销毁,如果频繁的去创建连接对象,销毁对象,会耗费内存资源
  2. 解决:提前先准备好连接对象,放到一个容器中,然后来了操作直接从这个容器中拿连接对象,用完之后还回去

xml文件

xml:可扩展性标记语言

  1. 标记语言:就是文件中由标签组成的 -> <标签名></标签名>
  2. 可扩展性:标签名可以自定义

连接池之C3p0(了解)

  1. 导入C3P0的jar包

c3p0-0.9.5.2.jar

mchange-commons-java-0.2.12.jar

下载地址:https://sourceforge.net/projects/c3p0/

  1. 创建c3p0配置文件(xml):
    1. 取名: c3p0-config.xml (名字必须是这个)

右键->新建->file->xxx.xml

b. c3p0-config.xml配置:

xml 复制代码
<c3p0-config>
  <!-- 使用默认的配置读取连接池对象 -->
  <default-config>
    <!--  连接参数 -->
    <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/msb_test01?rewriteBatchedStatements=true</property>
    <property name="user">root</property>
    <property name="password">root</property>

    <!--
    连接池参数
    初始连接数(initialPoolSize):刚创建好连接池的时候准备的连接数量
    最大连接数(maxPoolSize):连接池中最多可以放多少个连接
    最大等待时间(checkoutTimeout):连接池中没有连接时最长等待时间,单位毫秒
    最大空闲回收时间(maxIdleTime):连接池中的空闲连接多久没有使用就会回收,单位毫秒
    -->
    <property name="initialPoolSize">5</property>
    <property name="maxPoolSize">10</property>
    <property name="checkoutTimeout">2000</property>
    <property name="maxIdleTime">1000</property>
  </default-config>
</c3p0-config>

连接池之Druid德鲁伊(掌握)

  1. 概述: 是阿里巴巴开发的
  2. 导入jar包: druid-1.2.27.jar

下载地址:https://mvnrepository.com/artifact/com.alibaba/druid/1.2.27

  1. 配置文件: xxx.properties
properties 复制代码
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/msb_test01
username=root
password=root

#连接池参数
initialSize=5
maxActive=10
maxWait=1000

:::color5

  1. 读取配置文件

DruidDataSourceFactory.createDataSource(properties集合);

工具类:

java 复制代码
package com.luo.utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.mchange.v2.c3p0.ComboPooledDataSource;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * @author xiaobo
 * @date 2025/12/2 星期二
 * @description com.luo.utils
 */
public class DruidUtils {
    private DruidUtils() {
    }

    private static DataSource dataSource;

    static {
        try {
            // 创建Properties对象,用于存储配置文件中的键值对
            Properties properties = new Properties();

            // 通过类加载器获取druid.properties配置文件的输入流
            // getClassLoader()获取类加载器,getResourceAsStream()查找并加载资源文件
            InputStream resourceAsStream = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");

            // 从输入流中加载配置信息到Properties对象中
            properties.load(resourceAsStream);

            // 使用Druid连接池工厂类,根据配置创建数据源实例
            // 数据源包含连接池的所有配置信息,是获取数据库连接的核心对象
            dataSource = DruidDataSourceFactory.createDataSource(properties);

        } catch (Exception e) {
            // 捕获所有可能的异常并打印堆栈信息
            // 实际生产环境中应使用更规范的日志记录
            e.printStackTrace();
        }
    }

    public static Connection getConnection() {
        Connection connection = null;
        try {
            connection = dataSource.getConnection();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connection;

    }

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

DBUtils工具包

  1. commons-dbutils : 是简化jdbc开发步骤的工具包

  2. 核心对象:

    1. QueryRunner: 执行sql
    2. ResultSetHandler :处理结果集
    3. Dbutils: 关闭资源,事物处理
  3. 导入jar包

QueryRunner

  1. 构造: QueryRunner()
  2. 特点:
    1. 我们需要自己维护连接对象
    2. 支持占位符?
  3. 方法:
    1. int update(Connection conn ,String sql ,Object... params) -> 增删改
      1. conn:连接对象
      2. sql:sql语句
      3. params: 自动为sql中的?赋值 -> 直接传递给?
    2. queyr(Connection conn, String sql,ResultHandler res, Object... parmas) -> 查询
      1. conn:连接对象
      2. sql:sql语句
      3. res: 处理结果集,ResultHandler是一个接口,我们传入对应的实现类,不同的实现类对结果集有不同的处理
      4. parmas: 自动为sql中的?赋值
  4. 有参构造QueryRunner(DataSource)
  5. 特点:
    1. 不需要自己维护连接对象 ,也就是不需要传入 Connection 对象
    2. 支持占位符?

ResultSetHandler 结果集

BeanHandler
  1. 作用: 将查询出来的结果集中的第一行数据封装成javabean对象
  2. 方法:
    1. query(String sql , ResultSetHanlder res , Object... parmas) -> 有参QueryRunner时使用
    2. query(Connection conn, String sql , ResultSetHandler res , Object... parmas) ->无参QueryRunner时使用
  3. 构造: BeanHandler(Class type)

传递的class对象其实就是我们想要封装的javaben类的class对象

想查询出来的数据封装成哪个javabean对象,就写哪个javabean的class对象

  1. 怎么理解:

将查询出来的结果集为javabean中的成员属性赋值

java 复制代码
static void main() throws Exception{
QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
// 创建 BeanHandler对象
ResultSetHandler<Category> categoryBeanHandler = new BeanHandler<>(Category.class) ;
String sql = "select *  from category where cid = ?" ;
Category res = queryRunner.query(sql, categoryBeanHandler);
System.out.println(res);
}
BeanListHandler

:::color1

  1. 作用: 将查询出来的结果每一条数据都封装成一个一个的javabean对象,将这些javabean对象放到List集合中
  2. 构造: BeanListHandler(Class type)

传递的class对象其实就是我们想要封装的javaben类的class对象

想查询出来的数据封装成哪个javabean对象,就写哪个javabean的class对象

:::

java 复制代码
@Test
public void beanListHandlerTest() throws SQLException {

QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
String sql = "select  * from category";
// 创建BeanListHandler对象
BeanListHandler<Category> beanListHandler = new BeanListHandler<>(Category.class);

List<Category> categoryList = queryRunner.query(sql, beanListHandler);

System.out.println(categoryList);

}
ScalarHandler

:::color2

  1. 作用:主要是处理单值的查询结果,执行的select语,结果只有1个
  2. 构造:
    1. ScalarHandler(int columnIndex) -> 不常用 -> 指定第几行
    2. ScalarHandler(String columnName) -> 不常用 -> 指定列名
    3. ScalarHandler() -> 常用 默认代表查询结果的第一行第一列数据
  3. 注意:

Scalarhandler和聚合函数使用更有意义

:::

ColumnListHandler

:::color2

  1. 作用: 将查询出来的结构中的某一列数据,存储到List集合中
  2. 构造:

ColumnListHandler(int columnIndex) ->指定第几列

ColumnListHandler(String columnName) ->指定列名

ColumnListHandler() -> 默认显示查询结果中的第一列数据

  1. 注意:

ColumnListHandler可以指定泛型类型,如果不指定,返回的List泛型就是Object类型,可以不指定泛型

:::

事物

:::color2

  1. 事物就是:用来管理一组操作的(一组操作中包含了多条sql语句的),要么都成功,要么都失败
  2. 注意:
    1. mysql默认自带事物,但是mysql的自带事物,每次只能管理一条sql语句,所以想让mysql一次管理多条sql语句,需要关闭mysql自带事物,开启手动事务
  3. 方法: Connection中的方法:
    1. setAutoCommit(boolean auto Commit) -> 当参数为false,证明关闭mysql自带事物,自动开启手动事务
    2. void commit() -> 提交事务 -> 事物一旦提交,数据将永久保存,不能回到原来的数据
    3. void rollback() -> 回滚事物 -> 数据将恢复到原来的样子 -> 提前是事物没有提交

:::

java 复制代码
@Test
public void transferDemo() {
    QueryRunner queryRunner = new QueryRunner();
    Connection connection = DruidUtils.getConnection();

    try {
        // 开启事务  false:关闭mysql自带事物,开启手动事务
        connection.setAutoCommit(false);
        String outMoneySql = "update account set money = money - ? where name = ? " ;
        String intMoneySql = "update account set money = money + ? where name = ? " ;
        queryRunner.update(connection,outMoneySql,1000,"碎梦") ;
        System.out.println(1/0);
        queryRunner.update(connection,intMoneySql,1000,"龙吟") ;
        System.out.println("转账完成");
        // 完成之后提交事务
        connection.commit();
    } catch (SQLException e) {
        try {
            connection.rollback();
            System.out.println("转账失败");
        } catch (SQLException ex) {
            e.printStackTrace();
        }
        e.printStackTrace();

    }
}
相关推荐
醉舞经阁半卷书17 小时前
从零到1了解etcd
数据库·etcd
云老大TG:@yunlaoda3607 小时前
如何确保数据在腾讯云国际站代理商的归档存储服务中的安全性?
数据库·云计算·腾讯云
wuletaotao7 小时前
Redis 主从搭建笔记
数据库·redis·笔记
NocoBase7 小时前
如何快速搭建一个替换 Excel 的系统?(完整指南)
数据库·低代码·开源·excel·个人开发·零代码·无代码
7 小时前
TIDB——TIDB Server
数据库·分布式·tidb
Mr_wilson_liu7 小时前
通过DBeaver22.0.5 连接数据库ck(clickhouse)、pg(postgres)
数据库·clickhouse
Ashley_Amanda7 小时前
FICO 校验与替代技术点
数据库
黑白极客7 小时前
项目启动时报错找不到UserDetailsService
数据库·oracle
徐子元竟然被占了!!16 小时前
Linux-systemctl
linux·数据库·oracle