JDBC、数据库事务

本文介绍了JDBC的基本概念,包括JDBC的用途、如何通过JDBC连接MySQL数据库进行增删改查操作。此外,还讲解了JDBC的优缺点,如其简洁性但存在大量重复代码,以及缺乏内置连接池。接着,文章阐述了数据库事务的重要性,包括事务的四大特性:原子性、一致性、隔离性和持久性,并展示了MySQL中事务的开启、提交和回滚操作。
摘要由CSDN通过智能技术生成

1. JDBC

1.1 JDBC概述

JDBC(Java DataBase Connectivity) Java数据库技术
利用Java语言(Java程序)连接并访问数据库的一门技术
通过cmd窗口或者通过Navicat软件/sqlyog软件

1.2 为什么要学习JDBC

之前我们可以通过cmd窗口或者通过Navicat软件/sqlyog软件等软件连接数据库,对数据库中的数据进行增删改查操作。
但是,在企业开发中,更多的是通过程序来连接数据库。
像Mybatis/hibernate/DBUtils/Spring JdbcTemplate等框架底层也是在通过JDBC来连接数据库。

1.3 如何通过JDBC连接数据库

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TNrDzVUr-1626913814363)(README_files/1.jpg)]

  1. 概述:
    • 早期,不同的数据库厂商提供的数据库驱动(jar)包是各不相同的,开发人员在操作不同的数据库时需要学习该数据库对应的数据驱动(jar)包,这对于开发人员学习的成本太高。
    • 后来SUN公司就规定了JDBC这套规范(其实其中包含了大量的接口),要求不同的数据库厂商提供的驱动都来实现这套接口,这样一来,开发人员只要学会了这套接口,所有的数据库就都会操作了。
    • JDBC中主要包含两个包(java.sql和javax.sql),并且Java中已经包含这两个包了,但除了JDBC的包外,我们在操作数据库时还需要导入该数据库对应的驱动(jar)包。
  2. JDBC快速入门案例
    • 通过Java程序连接MySQL数据库,查询lz_db库中的account表中的所有数据

      • 准备所需要的数据库、表、表记录

          drop database if exists lz_db;
          create database lz_db charset utf8;
          use lz_db;
          create table account(
          	id int primary key auto_increment,
          	name varchar(50),
          	money double
          );
          insert into account values(null,'Tom',1000);
          insert into account values(null,'Andy',1000);
          insert into account values(null,'Tony',1000);  
        
    • 导入MySQL驱动包:

      • 找到jar包并复制到当前项目中(注意:这里只是将文件赋值过来,但并没有添加到项目中,程序还是无法使用这个jar包)
      • 还需要在当前项目中引用这个jar包:在jar包文件上右键 --> Build Path --> Add To Build Path
      • 如果要移除jar包:先解除引用(Remove from Build Path),后删除jar包
    • 创建cn.edu.JdbcDemo类,在这个类中通过六个步骤完成连接数据库

        public static void main(String[] args) throws  Exception {
        	//1. 注册数据库驱动(可以省略,建议加上)
        	Class.forName("com.mysql.cj.jdbc.Driver");
        	//2. 获取数据库连接
        	//Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/lz_db?characterEncoding=utf8&serverTimezone=Asia/Shanghai",
        			//"root", "root");
        	Connection conn = DriverManager.getConnection("jdbc:mysql:///lz_db?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
        			"root", "root");
        	System.out.println("执行");
        	//3. 获取传输器
        	Statement stat = conn.createStatement();
        	//4. 发送SQL到数据库执行,并返回执行结果
        	ResultSet resultSet = stat.executeQuery("select * from account");
        	//5. 处理结果(打印到控制台)
        	//rs.next() 返回true表示下一行有数据,就会进入循环获取下一行数据
        	while (rs.next()){
        		int id = rs.getInt("id");
        		String name = rs.getString("name");
        		double money = rs.getDouble("money");
        		System.out.println(id + "," + name + "," + money);
        	}
        	//6. 释放资源(越晚获取,越先关闭)
        	rs.close();
        	stat.close();
        	conn.close();
        }
      

运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8bJKnadz-1626913814365)(README_files/2.jpg)]

数据库查询结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HFUhfRlv-1626913814366)(README_files/3.jpg)]

1.4 如何通过JDBC增删改数据

/* 新增表记录:往account表中添加一条记录:null 'Mark' 3500 */
@Test
public void testAdd() throws Exception {
    Class.forName("com.mysql.cj.jdbc.Driver");
    Connection conn = DriverManager.getConnection("jdbc:mysql:///lz_db?charaterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
            "root", "root");
    Statement stat = conn.createStatement();
    String sql = "insert into account value(null,'Mark',3500)";
    int rows = stat.executeUpdate(sql);
    System.out.println("影响的行数:" + rows);
    stat.close();
    conn.close();
}

添加数据后:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XDqSadV1-1626913814367)(README_files/4.jpg)]

/* 修改表记录:将name为‘Mark’的金额修改为5000 */
@Test
public void testUpdate() {
    try {
        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql:///lz_db?charaterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
                "root", "root");
        Statement stat = conn.createStatement();
        String sql = "update account set money=5000 where name='Mark'";
        int rows = stat.executeUpdate(sql);
        System.out.println("影响的行数:" + rows);
        stat.close();
        conn.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

修改数据后:
在这里插入图片描述

/* 删除表记录:将name为‘Mark’的表记录删除 */
@Test
public void testDelete() throws Exception {
    Class.forName("com.mysql.cj.jdbc.Driver");
    Connection conn = DriverManager.getConnection("jdbc:mysql:///lz_db?charaterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false",
            "root", "root");
    Statement stat = conn.createStatement();
    String sql = "delete from account where name='Mark'";
    int rows = stat.executeUpdate(sql);
    System.out.println("影响的行数:" + rows);
    stat.close();
    conn.close();
}

删除数据后:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GmDdkPmU-1626913814369)(README_files/6.jpg)]

1.5 JDBC连接数据库的优点和缺点

  1. 优点:使用JDBC连接并访问数据库,相比使用第三方的框架连接访问数据库速度要快一些,因为这是最传统,最为底层的方法。
  2. 缺点:
    • JDBC中包含大量的重复代码(比如每次链接数据库都需要注册驱动、获取连接、获取传输器、处理结果、释放资源等),后期难以维护。
    • JDBC自身没有连接池,而框架(mybatis自带连接池)自带连接池,当需要连接自动从连接池中获取,用完连接不用关闭,再还回连接池中,这样可以提高执行效率。
    • JDBC中执行select查询语句的结果需要开发人员自己处理,如果时非常复杂的数据(比如查询的结果中列数非常多或者查询的数据来自多张表),处理起来非常麻烦,但框架可以帮我们处理。
    • 。。。

1.6 连接池概念

如果不使用连接池:

  • 用户每次需要连接访问数据库时,都需要创建一个连接(),基于这个连接去访问数据库中的数据,用完连接(Connection)之后会将连接关闭(close),其实每次创建链接和关闭连接(相比使用连接)需要消耗大量的时间和资源,导致程序的执行效率低下(特别是高并发的失火,比如京东618)
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jx7g82yN-1626913814371)(README_files/8.jpg)]

如果使用连接池:

  • 可以在程序启动之后,就创建一批连接放在一个池中(容器),当用户需要连接时,不用自己创建,而是从连接池中获取一个连接对象,再基于这个连接对象去访问数据库,用完连接之后,不用将连接关闭,而是还回连接池中。这样一来,用户使用的都是连接池中的这一批连接,可以减少连接创建和关闭的次数,提高程序的执行效率。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rAzo4NY5-1626913814373)(README_files/7.jpg)]

2. 数据库事务

  1. 什么是事务

    • DataBase Transaction(数据库事务)

    • 简单地说,就是将一堆的SQL语句绑定到一起执行,执行结果是:所有SQL都执行成功了才算成功,但凡有一条失败,就按全失败来处理(比如即使执行成功的语句,也会进行回滚,就是撤销当前的执行)。

    • 开启事务

        insert into account(null,'aaa',2000);
        update account set money = money + 100;
        。。。
      
    • 关闭事务(提交/回滚)

  2. 事务的四大特征

    • 原子性:原子曾被认为是最小单位,不能被分割,这里的原子性是指:事务中的所有SQL是一个整体,不能被分割,不存在一部分SQL执行成功,而另一部分SQL执行失败,都执行成功才算成功,有一条失败就算失败。
    • 一致性:在事务执行前后(提交/回滚)的业务数据之和是保持一致的。
    • 隔离性:在事务并发时,一个事务理论上看不到另一个事务的状态,即事物之间是相互隔离开来的。一个事务只能看到另外一个事务没开始之前的数据状态,或者只能看到另外一个事务已经结束的数据状态。
    • 持久性:一旦事务提交后,事务中对数据的更新操作会持久的保存到数据库中(最终是更新到硬盘的数据文件里)。反过来说,在事务提交之前,对数据的更新操作只是一个临时的数据,没有真正的去修改数据库。
      • 持久存储
      • 非持久存储
  3. MySQL中的事务操作

    • 默认情况下,MySQL中每执行一条上去了语句,其实都是一个单独的事务,即使不开启事务,每执行一条SQL之前,自动开启事务,执行完这条立即提交事务。
    • 如果需要在一个事务中包含多条SQL语句,那么就需要手动开启事务,和手动结束事务。
    • 开启事务:begin; | start transaction;
    • 结束事务:提交(commit),回滚(rollback)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘刘刘刘刘先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值