传智播客---什么是JDBC事物管理与数据库连接池

来咱们传智播客也很长一段时间了,今天老师给我们带来了力量,带来了动力,是什么力量?是什么动力呢?是最近一个刚毕业的班级的同学就业名单,同学的就业率都达到%98了,这个数字让我们在坐的学生都特别的兴奋啊!!!而且这还不算,更兴奋的那肯定是同学们所期待的薪资啊,平均都达到6000元了啊!!!当时全部都沸腾了,班主任特幽默,很淡定的来了句,你们激动什么啊,我们学校每一季的毕业生就业率都是这样的,待遇有的都比这个还高呢。当时心里就想真是老师您见多了啊,都习惯了。之后大家就更加的努力学习了,因为我们看到了希望,加油吧!小伙子,成功离你不远了....!

给大家讲讲今天所学到的知识,嘿嘿

事务概念:围绕着一个业务功能,产生一组操作,这组操作要么全都成功,要么全都失败 ,这组操作称为一个事务
在MySQL中事务默认是自动提交的,每当执行一条SQL,就会提交一个事务 (一条SQL 就是一个事务)
Oracle 中事务默认 不自动提交,需要在执行SQL 语句后 通过commint 手动提交事务
mysql管理事务的方式与步骤:
 方式一
 同时事务管理SQL 语句
 start transaction  开启事务
 rollback  回滚事务 (将数据恢复到事务开始时状态)
 commit   提交事务 (对事务中进行操作,进行确认操作,事务在提交后,数据就不可恢复)
 方式二:
 数据库中存在一个自动提交变量 ,通过 show variables like '%commit%'可以查看;
 ---- 如果autocommint 值是 on,说明开启自动提交
 关闭自动提交 set autocommit = off 或者 set autocommit = 0
 如果设置autocommit 为 off,意味着以后每条SQL 都会处于一个事务中,相当于每条SQL执行前 都执行 start transaction
 在Oracle中 autocommit 默认就是 off
在代码中JDBC控制事务的语句:
 Connection.setAutoCommit(false); //  相当于start transaction开启事物
 Connection.rollback(); //相当于rollback回滚事物
 Connection.commit();  //相当于commit提交事物
 JDBC提供事务回滚点接口 Savepoint, 如果在事务中进行savepoint设置,可以在事务回滚时,回滚到指定回滚点
事务的四大特性 : ACID  原子性、一致性、隔离性、持久性
 1、原子性:事务中操作不可分割,要么都成功、要么都失败
 2、一致性:事务操作,必须保证数据完整性一致 ,例如:删除一个公司部门的数据,包括部门基本信息、部门人力信息、财务信息
 ,如果财务信息依赖部门基本
 信息,删除时,保证删除之前财务信息依赖基本信息,删除后,部门基本信息和财务信息同时删除,如果只删除基本信息,
 部门财务信息依赖数据丢失,破坏数据的一致性
 3、隔离性:多个事务同时操作一条数据记录,事务之间应该相互隔离,不互相影响
 4、持久性:事务一旦提交后,数据将永久改变,不能恢复
如果数据库不考虑并发线程 事务访问的隔离,将引发的几个问题:
 1、脏读 :指一个事务读取另一个事务未提交的数据
 2、不可重复读:在一个事务先后两次读取发生数据不一致情况,第二次读取到另一个事务已经提交数据 (强调数据更新 update)
 3、虚读 : 在一个事务中,第二次读取发生数据记录数的不同 ,读取到另一个事务已经提交数据 (强调数据记录变化 insert )
数据库内部定义了四种隔离级别,用于解决三种隔离问题:
 1、read uncommited 最低事务级别,允许以上三类隔离问题的发生
 2、read commint 不会发生脏读,允许不可重复读和虚读发生
 3、repeatable read 不会发生脏读、不可重复读,允许虚读发生
 4、serializable 事务最高级别,所有相同数据事务操作,都会串行进行,不存在并发,不存在三类隔离问题
 数据库的四种隔离级别从安全性来比较:serializable > repeatable read > read committed > read uncommitted
 数据库的四种隔离级别从性能来比较 :serializable < repeatable read < read committed < read uncommitted
 操作数据库内部隔离级别
 set session transaction isolation level 设置事务隔离级别
 select @@tx_isolation 查询当前事务隔离级别
 实际开发中,通常不会选择serializable和read uncommitted ,mysql默认隔离级别repeatable read ,oracle默认隔离级别read committed
JDBC程序中能否指定事务的隔离级别 ?
Connection接口中定义事务隔离级别四个常量:
static int TRANSACTION_READ_COMMITTED
          指示不可以发生脏读的常量;不可重复读和虚读可以发生。
static int TRANSACTION_READ_UNCOMMITTED
          指示可以发生脏读 (dirty read)、不可重复读和虚读 (phantom read) 的常量。
static int TRANSACTION_REPEATABLE_READ
          指示不可以发生脏读和不可重复读的常量;虚读可以发生。
static int TRANSACTION_SERIALIZABLE
          指示不可以发生脏读、不可重复读和虚读的常量。
通过 void setTransactionIsolation(int level) 设置数据库隔离级别
Connection.setTransactionIsolation(可以传入Connection接口中定义的常量级别); 
事务在企业开发中常见问题:lost update 丢失更新
描述:两个事务同时更新同一行数据,第二个事务提交数据,覆盖了第一个事务提交更新数据
解决方案:
方案一:悲观锁 (假设丢失更新一定会发生 ) ----- 利用数据库内部锁机制,管理事务
方案二:乐观锁 (假设丢失更新不会发生)------- 采用程序中添加版本字段解决丢失更新问题
一、悲观锁
mysql数据库内部提供两种常用 锁机制:共享锁(读锁)和排它锁(写锁)
允许一张数据表中数据记录,添加多个共享锁,添加共享锁记录,对于其他事务可读不可写的
一张数据表中数据记录,只能添加一个排它锁,在添加排它锁的数据 不能再添加其他共享锁和排它锁,对于其他事物可读不可写的
*** 所有数据记录修改操作,自动为数据添加排它锁
添加共享锁方式:select * from account lock in share mode ;
添加排它锁方式:select * from account for update;
* 锁必须在事务中添加 ,如果事务结束了 锁就释放了
解决丢失更新:事务在修改记录过程中,锁定记录,别的事务无法并发修改

二、乐观锁
采用记录的版本字段,来判断记录是否修改过 -------------- timestamp
timestamp 可以自动更新
create table product (
   id int,
   name varchar(20),
   updatetime timestamp
);
insert into product values(1,'冰箱',null);
update product set name='洗衣机' where id = 1;
* timestamp 在插入和修改时 都会自动更新为当前时间
解决丢失更新:在数据表添加版本字段,每次修改过记录后,版本字段都会更新,如果读取是版本字段,与修改时版本字段不一致,说明别人进行修改过数据 (重改)
 数据库连接池的原理:一次性创建多个连接,将多个连接缓存在内存中,形成数据库连接池(内存数据库连接集合),如果应用程序需要操作数据
 库,只需要从连接池中获取一个连接,使用后,并不需要关闭连接,只需要将连接放回到连接池中。
 * 好处:节省创建连接与释放连接降低性能消耗 ---- 连接池中连接起到复用的作用 ,提高程序性能
 JDBC定义 javax.sql.DataSource 数据库连接池接口,只需要实现该接口,就可以去定义数据库连接池
 编写实现连接池需要注意的事项:
 1、一次性批量创建多个数据库连接,保存集合对象中 ----- 就是连接池
 2、实现DataSource接口中 getConnection , 从连接池中取出连接
 3、在用户使用连接后,能够将连接放回到连接池
自定义连接池程序问题:
 1、尽量不要使用具体对象类型的引用
 MyDataSource dataSource = new MyDataSource(); 应该写为 DataSource dataSource = new MyDataSource();
 2、使用自定义方法 addBackToDBPool 将连接放回连接池 ,需要用户在使用时需要记忆额外API
  解决:让用户定义连接池时 DataSource dataSource = new MyDataSource();  
  在用户使用连接后,应该调用conn.close();完成将连接放回到连接池
 这时要对close方法进行方法增强
 增强close方法,不真正关闭连接,而是将连接放回到连接池
增强java中一个方法存在三种方式:1、继承 方法覆盖 2、包装 3、动态代理
 1、继承方法覆盖,对原有类方法进行加强
 注意:必须控制对象构造,才能使用继承的方式对方法进行加强
 2、包装 (装饰者)
 编写包装类 1) 必须要与被装饰对象,有相同父类或者实现相同接口  2) 必须将被装饰对象传递给装饰者 (在构造函数中)
 包装是一种通用方法加强措施,不管是否控制目标对象创建,都可以完成方法加强
 3、动态代理
 原理:利用类加载器 ,在内存中根据目标类加载器和接口 创建一个代理对象 ,通过代理对象完成对原有对象方法进行加强
 注意:被代理对象,必须实现接口
 应用场景:也是只有存在目标对象,就可以通过动态代理进行加强

常用开源连接池
1、Apache DBCP
2、C3P0
3、Tomcat内置连接池

一、DBCP 连接池
 DBCP 是Apache 的commons 项目的一个子项目
 去官网下载 dbcp 和 pool 的jar包 ,DBCP 依赖 POOL的jar包
 复制两个jar 到WEB-INF/lib下
 DBCP连接池 核心类 BasicDataSource
 * 任何数据库连接池,需要数据库连接,必须通过JDBC四个基本参数构造
 1、手动设置参数
   // 使用连接池
   BasicDataSource basicDataSource = new BasicDataSource();
   // 设置JDBC四个基本参数
   basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");加载数据库驱动
   basicDataSource.setUrl("jdbc:mysql:///day14");连接数据库
   basicDataSource.setUsername("root");传入数据库使用用户名
   basicDataSource.setPassword("abc");传入密码
 2、通过配置文件
   // 根据属性参数 获得连接池
   InputStream in = DBCPTest.class.getResourceAsStream("/dbcp.properties");
   Properties properties = new Properties();
   // 装载输入流
   properties.load(in);
   DataSource dataSource = BasicDataSourceFactory.createDataSource(properties);

二、C3P0 连接池
 主流开源连接池,在Hibernate和Spring 都提供对C3P0连接池支持
 去下载c3p0 开发包 http://sourceforge.net
 将c3p0的jar 复制WEB-INF/lib下
 1、手动
   // 核心连接池类
   ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
   // 设置四个JDBC基本连接属性
   comboPooledDataSource.setDriverClass("com.mysql.jdbc.Driver");
   comboPooledDataSource.setJdbcUrl("jdbc:mysql:///day14");
   comboPooledDataSource.setUser("root");
   comboPooledDataSource.setPassword("abc");

 2、在src下新建c3p0-config.xml
 ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(); 会自定加载配置文件

 常用基本连接池属性
  acquireIncrement  如果连接池中连接都被使用了,一次性增长3个新的连接
  initialPoolSize  连接池中初始化连接数量 默认:3
  maxPoolSize      最大连接池中连接数量 默认:15连接
  maxIdleTime      如果连接长时间没有时间,将被回收 默认:0 连接永不过期
  minPoolSize      连接池中最小连接数量 默认:3
三、tomcat服务器内置连接池 (使用Apache DBCP)
 配置tomcat 内置连接池,通过JNDI方式 去访问tomcat的内置连接池
 JNDI Java命名和目录接口,是JavaEE一项技术 ,允许将一个Java对象绑定到一个JNDI容器(tomcat)中 ,并且为对象指定一个名称
 通过javax.naming 包 Context 对JNDI 容器中绑定的对象进行查找,通过指定名称找到绑定Java对象
 操作步骤
 1、配置使用tomcat 内置连接池 配置<context> 元素
 context元素有三种常见配置位置
 1) tomcat/conf/context.xml 所有虚拟主机,所有工程都可以访问该连接池
 2) tomcat/conf/Catalina/localhost/context.xml 当前虚拟主机(localhost)下所有工程都可以使用该连接池
 3) 当前工程/META-INF/context.xml 只有当前工程可以访问该连接池
 <Context>
   <Resource name="jdbc/EmployeeDB" auth="Container"
    type="javax.sql.DataSource" username="root" password="abc"
    driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql:///day14"
    maxActive="8" maxIdle="4"/>
 </Context>
 * 必须先将mysql驱动jar包 复制tomcat/lib下
 * 在tomcat启动服务器时,创建连接池对象,绑定 jdbc/EmployeeDB 指定名称上
 2、通过运行在JNDI容器内部的程序(Servlet/JSP)去访问tomcat内置连接池
 Context context = new InitialContext();
 Context envCtx = (Context)context.lookup("java:comp/env"); 固定路径
 DataSource datasource = (DataSource) envCtx.lookup("jdbc/EmployeeDB"); 通过绑定名称,查找指定java对象

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值