ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

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

2021-05-15 22:31:28  阅读:134  来源: 互联网

标签:事务 jdbc jt money 数据库 db mysql 100


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)	

	
	

标签:事务,jdbc,jt,money,数据库,db,mysql,100
来源: https://blog.csdn.net/m0_56057949/article/details/116864902

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有