数据库之mysql笔记二 jdbc+事务介绍

本文介绍了JDBC的基本概念、使用步骤以及其在连接数据库时的优势和不足。通过实例展示了如何通过JDBC连接MySQL数据库,进行数据的增删改查操作。此外,详细解释了数据库事务的四大特性,并提供了MySQL中的事务操作示例,强调了事务在确保数据一致性中的重要性。
摘要由CSDN通过智能技术生成
1: JDBC
1.1: 什么是JDBC
	JDBC(Java DataBase Connectivity) Java数据库连接
	其实就是利用Java语言(Java程序)连接并访问数据库的一门技术
	
1.2: 为什么要学习JDBC
	之前我们可以通过 CMD窗口 或者 通过 Navicat/Sqlyog等软件 连接数据库, 对数据库中的数据进行增删改查操作.
	但是,将来我们在企业开发中,更多的是通过程序来连接数据库, 而我们学的是Java开发,通过Java程序连接数据就必须用到JDBC这门技术!
	像Mybatis/hibernate/DBUtils/Spring JdbcTemplate等框架底层也是在通过JDBC来连接数据库

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

1.3.2: JDBC快速入门案例
	通过Java程序连接mysql数据库, 查询jt_db库中的account表中的所有数据
	1: 准备所需要的数据库、表、表记录
		-- --------------------------------------------
		drop database if exists jt_db;
		create database jt_db charset utf8;
		use jt_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);
		-- --------------------------------------------

	2: 导入mysql驱动包(mysql-connector-java-8.0.11.jar)
		找到 mysql-connector-java-8.0.11.jar 文件 并复制
		将这个文件复制到项目/lib目录下, 注意,这里只是将jar文件复制过来了
		但并没有添加到项目中, 所有程序中还是无法使用这个jar包
		还需要在当前项目中引用这个jar包: 
			在jar文件上右键--> Build Path --> Add To Build Path
		如果要移除引用的jar包: 在Referenced Libraries下面找到这个引用后的包, 在包上右键--> Build Path --> Remove From Build Path
		
	3: 创建cn.tedu.JdbcDemo类,在这个类中通过六个步骤完成连接数据库操作
		--------------------------------------------
		/**
		 * JDBC的快速入门程序
		 * 	查询jt_db库中account表中的所有记录
		 * 	select * from account;
		 */
		public class JdbcDemo1 {
			public static void main(String[] args) throws Exception {
				//1.注册数据库驱动(可以省略,但建议加上)
				Class.forName( "com.mysql.cj.jdbc.Driver" );
				//2.获取数据库连接( alt+shift+L )
				/*
				Connection conn = DriverManager.getConnection(
					"jdbc:mysql://localhost:3306/jt_db?characterEncoding=utf-8&serverTimezone=Asia/Shanghai", 
					"root", "root"); */
				Connection conn = DriverManager.getConnection(
						"jdbc:mysql:///jt_db?characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false", 
						"root", "root");
				
				//3.获取传输器
				Statement stat = conn.createStatement();
				//4.发送sql到数据库执行,并返回执行结果
				ResultSet rs = stat.executeQuery( "select * from account" );
				
				System.out.println( rs );
				
				//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();
			}
		}
		--------------------------------------------

1.4: 如何通过JDBC增删改数据
	--------------------------------------------
	/* 新增表记录: 往account表中添加一条记录: null 'hellen' 3500 */
	@Test
	public void testAdd() throws Exception {
		//注册驱动
		Class.forName( "com.mysql.cj.jdbc.Driver" );
		//获取连接
		Connection conn = DriverManager.getConnection( 
			"jdbc:mysql:///jt_db?characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false", 
			"root", "root" );
		//获取传输器
		Statement stat = conn.createStatement();
		//执行SQL语句, 返回执行结果
		String sql = "insert into account value(null, 'hellen', 3500 )";
		int rows = stat.executeUpdate(sql); 
		//处理结果
		System.out.println( "影响的行数为: "+rows );
		//释放资源
		stat.close();
		conn.close();
	}
	
	--------------------------------------------
	/* 修改: 将name为'hellen'的金额修改为5000 */
	@Test
	public void testUpdate() {
		
	}
	
	--------------------------------------------
	/* 修改: 将name为'tom'的记录删除! */
	@Test
	public void testDelete() {
		
	}
	--------------------------------------------

1.5: JDBC连接数据库的优点和缺点
	1)优点:使用JDBC连接并访问数据库 相比使用第三方的框架连接访问数据库速度要快一些!因为这是最为传统,最为底层的方法。
	
	2)缺点:
		a) JDBC中包含大量重复的代码(比如每次连接数据库都需要 注册驱动、获取连接、获取传输器、处理结果、释放资源等),后期难以维护
		b) JDBC自身没有连接池,而框架(mybatis自带连接池)自带连接池,当需要连接直接从连接池中获取,用完连接不用关闭,再还回连接池中,这样可以提高执行效率!
		c) JDBC中执行select查询语句的结果需要开发人员自己手动处理, 如果是非常复杂的数据(比如查询的结果中列数非常多或者查询的数据来自多张表)处理起来是非常麻烦的,但框架可以帮我们处理!
		...
	
1.6: 连接池概念
	如果不使用连接池: 
		用户每次需要连接访问数据库时, 都需要创建一个连接(Connection), 基于这个连接去访问数据库中的数据, 用完连接(Connection)后会将连接关闭(close), 其实每次创建连接和关闭连接(相比使用连接)需要消耗大量的时间和资源,导致程序的执行效率低下(特别是高并发的时候,比如京东618)

	如果使用连接池:
		可以在程序一启动之后,就创建一批连接放在一个池中(容器), 当用户需要连接时, 不用自己创建, 而是从连接池中获取一个连接对象, 再基于这个连接对象去访问数据库, 用完连接后, 不用将连接关闭, 而是还回连接池中。这样一来,用户使用的都是池中的这一批连接,可以减少连接创建和关闭的次数,提高程序的执行效率!

2: 数据库事务
2.1: 什么是事务
	DataBase Transaction(数据库事务)
	简单的说: 事务就是将一堆的SQL语句绑定在一起执行, 执行结果是: 所有SQL都执行成功了才算成功, 但凡有一条失败, 就按全失败来处理(比如即使执行成功的语句,也会进行回滚,就是撤销当前的执行)。
	开启事务
		insert into account(null, 'aaa', 2000);
		update account set money = money+100;
		...
	关闭事务(提交/回滚)
	--------------------------------------------
	以转账为例: A、B账户各有1000元,A给B转账100元
	A账户减去100元:update account set money=money-100 where name='A';
	B账户加上100元:update account set money=money+100 where name='B';
	如果上面两条语句执行时,没有事务,如果第一条成功,但第二条失败了!
	反之,如果第一条失败了,但第二条成功了!
	所以如果想保证上面的两条SQL语句同时成功或者同时失败,可以将这两条SQL添加到一个事务中。
	--------------------------------------------
		
2.2: 事务的四大特征(面试题)
	原子性:原子曾被认为是最小单位,不能被分割, 这里的原子性其实是指:
		事务中的所有SQL是一个整体,不能被分割。不存在一部分SQL执行成功,而另一部分SQL执行失败,都执行成功才算成功,有一条失败就算失败!
	--------------------------------------------
	一致性:在事务执行前后(不管事务最后是提交还是回滚)的业务数据之和是保持一致的!
	--------------------------------------------
		以转账为例: A、B账户各有1000元,A给B转账100元
		A账户减去100元:update account set money=money-100 where name='A';
		B账户加上100元:update account set money=money+100 where name='B';
		如果上面的SQL是在一个事务中执行的, 可以保证A和B的账户金额之和在转账前、转账后是一致的!
		情况1: 上面的SQL都成功了, 事务最后提交了
			A账户减去100 = 900;
			B账户加上100 = 1100;
			A+B总和是2000, 和转账前总金额一致!
		情况1: 上面的SQL有一条或者两条失败了, 按全失败处理, 事务最后回滚了
			A的钱没少, B的钱也没多, 和转账前一致!
	--------------------------------------------
	隔离性:在事务并发时, 一个事务理论上看不到另外一个事务的状态, 也就是说事务之间是相互隔离开来的!
		
		一个事务只能看到另外一个事务没开始之前的数据状态, 或者只能看到另外一个事务已经结束之后的数据状态!
		事务1--开启事务, 查询A+B的账户金额之和
			A+B账户金额之和: 2000
		事务2--开启事务, 完成一个转账操作(A给B转账100元)
			A减去100元=900
			--------------
			B加上100元=1100
	--------------------------------------------
	持久性:一旦事务提交之后, 事务中对数据的更新操作会持久的保存到数据库中(最终是更新到硬盘的数据文件里)
		反过来说, 在事务提交之前, 对数据的更新操作只是一个临时的数据, 没有真正的去修改数据库。
		-- 开启事务:
		A减去100元: update account set money=money-100 where name='A'; 900元
		B加上100元: update account set money=money+100 where name='B'; 1100元
		-- 结束事务(提交,回滚)
	
2.3: mysql中的事务操作
	在默认情况下, mysql中每次执行一条SQL语句, 其实都是一个单独的事务
	即使你不开启事务, 每执行一条SQL之前, 自动开启事务, 执行完这条立即提交事务

	如果需要在一个事务中包含多条SQL语句, 那么就需要手动开启事务, 和手动结束事务
	开启事务: begin; | start transaction;
	结束事务: 提交(commit), 回滚(rollback)
	-- ------------------------------------------
	create database if not exists jt_db charset utf8;
	use jt_db;
	create table acc(
		id int primary key auto_increment,
		name varchar(50),
		money double
	);
	insert into acc values(null, 'A', 1000);
	insert into acc values(null, 'B', 1000);
	-- ------------------------------------------
	下面演示mysql开启事务和提交事务操作:
	-- ------------------------------------------
	MariaDB [jt_db]> -- 开启事务(也可以用 start transaction; 开启事务)
	MariaDB [jt_db]> begin;
	Query OK, 0 rows affected (0.000 sec)

	MariaDB [jt_db]> -- A账户减去100元
	MariaDB [jt_db]> update acc set money=money-100 where name='A';
	Query OK, 1 row affected (0.000 sec)

	MariaDB [jt_db]> -- B账户加上100元
	MariaDB [jt_db]> update acc set money=money+100 where name='B';
	Query OK, 1 row affected (0.000 sec)

	MariaDB [jt_db]> select * from acc; -- 现在未提交事务, 下面的数据是临时数据
	+----+------+-------+
	| id | name | money |
	+----+------+-------+
	|  1 | A    |   900 |
	|  2 | B    |  1100 |
	+----+------+-------+
	2 rows in set (0.000 sec)

	MariaDB [jt_db]> -- 提交事务(换成 rollback; 就是回滚事务!)
	MariaDB [jt_db]> commit; 
	Query OK, 0 rows affected (0.001 sec)

	MariaDB [jt_db]> select * from acc; -- 现在已提交事务, 下面的数据已经持久更新到数据库了
	+----+------+-------+
	| id | name | money |
	+----+------+-------+
	|  1 | A    |   900 |
	|  2 | B    |  1100 |
	+----+------+-------+
	2 rows in set (0.000 sec)	

	
	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值