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();

    }
}
相关推荐
小陈工4 小时前
Python Web开发入门(十七):Vue.js与Python后端集成——让前后端真正“握手言和“
开发语言·前端·javascript·数据库·vue.js·人工智能·python
科技小花8 小时前
数据治理平台架构演进观察:AI原生设计如何重构企业数据管理范式
数据库·重构·架构·数据治理·ai-native·ai原生
一江寒逸8 小时前
零基础从入门到精通MySQL(中篇):进阶篇——吃透多表查询、事务核心与高级特性,搞定复杂业务SQL
数据库·sql·mysql
D4c-lovetrain8 小时前
linux个人心得22 (mysql)
数据库·mysql
阿里小阿希9 小时前
CentOS7 PostgreSQL 9.2 升级到 15 完整教程
数据库·postgresql
荒川之神9 小时前
Oracle 数据仓库雪花模型设计(完整实战方案)
数据库·数据仓库·oracle
做个文艺程序员9 小时前
MySQL安全加固十大硬核操作
数据库·mysql·安全
不吃香菜学java9 小时前
Redis简单应用
数据库·spring boot·tomcat·maven
一个天蝎座 白勺 程序猿10 小时前
Apache IoTDB(15):IoTDB查询写回(INTO子句)深度解析——从语法到实战的ETL全链路指南
数据库·apache·etl·iotdb
不知名的老吴10 小时前
Redis的延迟瓶颈:TCP栈开销无法避免
数据库·redis·缓存