事务和连接池

事务

  • 事务的概念:事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功;

例如:A----B转帐,对应用如下两条sql语句
update account set money=money-1000 where name=‘aaa’;
update account set money=money+1000 where name=‘bbb’;

  • 数据库开启事务命令

shatrt transaction或begin 开启事务
Rollback 回滚事务
Commit 提交事务

  • JDBC操作事务
    在这里插入图片描述
  • 事务的特性

原子性:指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生.
一致性:事务必须使数据库从一个一致性状态,换到另一个一致性状态,转帐前和转帐后总金额都不变。
隔离性:事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其它事务的操作数据所干扰,多个并发事务之间要相互隔离。
持久性:指一个事务一旦被提交,它对数据库中的数据改变就是持久性的,接下来,就算数据库有什么故障也不应该对其有任何影响。

  • 事务的隔离级别

赃读:指一个事务读取到另一个事务没有提交的事务
不可重复读:在一个事务内读取表中的某一行数据,多次读取结果不同,一个事务读取到了另一个事务提交后的数据,(Update)
虚读:是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致(insert)

数据库通过设置事务的隔离级别防止以上情况的发生:

1、READ UNCOMMITTED:赃读,不可重复读,虚读都有可能发生
2、READ COMMITTED:避免赃读。不可重复读和虚读有可能发生(Oracle)
4、REPEATABLE READ:避免赃读,不可重复读。虚读有可能发生(mysql)
8、SERIALIZABLE:避免赃读、不可重复读、虚读。
级别越高、性能越低、数据更安全

mysql中

查看当前事务的隔离级别:SELECT @@TX_ISOLATION;
更改当前的事务隔离级别:SET TRANSACTION ISOLATIONLEVEL 四个级别之一
设置隔离级别必须在事务之前

  • JDBC控制事务的隔离级别
    Connction中有五个常量
    在这里插入图片描述
    设置隔离级别:必须在开启事务之前
    Connection.setTransactionIsolation(int level);

在这里插入图片描述

连接池

  • 什么是数据库连接池?

数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新再创建一个 ;释放空闲时间超过最大空闲时间的数据库连接起来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能
目的:解决建立数据库连接耗费资源和时间很多的问题,提高性能
在这里插入图片描述

  • 模拟连接池
    在这里插入图片描述
  • 编写标准的数据源(连接池)(装饰设计模式)
    自定义数据库池连接池要实现javax.sql.DataSource接口
    由于DataSource中没有close()方法
    所以我们自己写一个类实现接口Connection重写close(),并通过构造把连接和连接池传进去
    如下代码
    实现java规定的连接池标准
    在这里插入图片描述
    实现Connection并重写close()
    在这里插入图片描述
    使用连接池创建连接Test
    在这里插入图片描述
  • 适配器实现连接池
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

常用的数据源配置

  • DBCP
    apache推出的Database Connection pool (数据库连接池)
    使用步骤:
    1、添加jar包
    2、添加属性资源文件
    3、编写工具类
    4、使用工具类

1、添加jar包如下图
在这里插入图片描述
2、添加属性资源文件
在这里插入图片描述
3、编写工具类
在这里插入图片描述
4、使用工具类
在这里插入图片描述

  • C3P0
    使用步骤
    1、添加jar包
    2、编写配置文件
    3、编写工具类
    4、使用工具类

1、添加jar包
在这里插入图片描述
2、编写配置文件
在这里插入图片描述
3、编写工具类在这里插入图片描述
4、使用工具类
在这里插入图片描述

DBUtils

  • 什么是DBUtils,它的作用?

DBUtils是java编程中的数据库操作实用工具。小巧简单实用。
DBUtils封装了对JDBC的操作,简化了JDBC操作。可以少写代码
1、对于数据表的读操作,他可以把结果转换成List,Array,Set等Java集合,便于程序员操作;
2、对于数据表的写操作,也变得很简单。(只需要写sql语句)
3、可以使用数据源,使用JNDI,数据库连接池等技术来优化性能,重用已经构建好的数据库连接对象。

  • DBUtils的三个核心对象

QueryRunner类 :提拱了对sql语句操作的API
主要有三个方法:
1、query();用于执行select语句
2、update();用于执行update、insert、delete
3、batch();批处理

ResultSetHandler接口 (结果集)
用于定义select操作后,怎样封装结果集
DBUtils
它就是一个工具类,定义了关闭资源与事务处理的方法

  • 快速入门
    1、导入jar包
    2、创建QueryRunner对象
    3、使用query方法执行select语句
    4、使用ResultSetHandler封装结果集
    5、使用DButils类释放资源

分两种方法实现一个查询的操作
在这里插入图片描述
1在这里插入图片描述
2在这里插入图片描述

  • QueryRunner对象
    1、构造函数:new QueryRunner();它可以手动创建事务
    也就是说此对象调用的方法(如:query、update、batrch)参数中要有Connection对象
    new QueryRunner(DataSource ds);它的事务是自动控制的,一个sql一个事务
    此对象调用的方法(如:query、update、batrch)参数中无需Connection对象
    在这里插入图片描述
    测试CRUD+批处理
public class TestCRUD {
	//增
	@Test
	public void testInsert() {
		QueryRunner or = new QueryRunner(C3P0Utils.getDataSource());
		try {
			int index = or.update("insert into user values(null,?,?,?)","成龙", 30, "男");
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	//删
	@Test
	public void testDelete() {
		QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
		try {
			qr.update("delete from user where id=?", 7);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	//查
	@Test
	public void testSelect() {
		QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
		try {
			List<User> list = qr.query("select * from user", new BeanListHandler<User>(User.class));
		for(User user : list) {
			System.out.println(user);
		}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	//改
	@Test
	public void testUpdate() {
		QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
		try {
			qr.update("update user set age=? where username=?", 37,"成龙");
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	//批处理,只能执行相同的sql语句
	@Test
	public void testBatch() {
		QueryRunner qr = new QueryRunner(C3P0Utils.getDataSource());
		Object arr[][] = {
				{"张静", 17, "女"},
				{"张蔓", 12, "女"}
		};
		try {
			qr.batch("insert into user values(null,?,?,?)", arr);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
  • ResultSetHandler的9个处理器

1、ArrayHandler:适合取一条记录,把该条记录的每列值封装到一个Object[]中
2、ArrayListHandler:适合取多条记录,把每一条记录的每列值封装到一个Object数组中,再把数组封装到一个list集合中.
3、ColumnListHandler:取某一列的值并封装到一个List集合中
4、KeyedHandler:取多条记录,把每一条记录封装到一个Map集合中,再把这个map封装到另一个map中,key为指定的字段值
5、MapHandler:适合取一条记录,把当前记录的列名和列值放到一个Map中
6、MapListHandler:适合取多条记录。把每条记录的列名和列值封装到一个map中,再把这个map封装到一个list中
7、ScalarHandler:适合取单行单列数据
8、BeanHandler
9、BeanListHandler

ThreadLocal

  • 模拟ThreadLocal的设计,让大家明白他的作用.
 public class ThreadLocal {
 	private Map<Runnable, Object> container = new Map<Runnble, Object>();
 	public void set(Object value) {
		container.put(Thread.currentThread(), value); //用当前线程作为key
	}
	public Object get() {
		return container.get(Thread.currentThread());
	}
	public void remove() {
		container.remove(Thread.currentThread());
	}
 }

总结:调用该类的get方法,返回的都是当前线程放入的数据,线程局部变量

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值