Hibernate事务、缓存和连接池
一、事务
1、数据库事务的概念
数据库事务是指由一个或多个SQL语句组成的工作单元,这个工作单元中的SQL语句相互依赖,如果有一个SQL语句执行失败,就必须撤销整个工作单元。在并发环境中,多个事务同时访问相同的数据资源时,可能会造成各种并发问题,可通过设定数据库的事务隔离级别来避免,还可采用悲观锁和乐观锁来解决丢失更新这一并发问题。
数据库事务必须具备ACID特征:
A:Atomic原子性,整个事务不可分割,要么都成功,要么都撤销。
C:Consistency一致性,事务不能破坏关系数据的完整性和业务逻辑的一致性,例如转账,应保证事务结束后两个账户的存款总额不变。
I:Isolation隔离性,多个事务同时操纵相同数据时,每个事务都有各自的完整数据空间
D:Durability持久性,只要事务成功结束,对数据库的更新就必须永久保存下来,即使系统发生崩溃,重启数据库后,数据库还能恢复到事务成功结束时的状态。
2、事务边界声明
只要声明了一个事务,数据库系统就会自动保证事务的ACID特性。
声明事务包含:
事务的开始边界
事务的正常结束边界(commit):提交事务,永久保存
事务的异常结束边界(rollback):撤销事务,数据库回退到执行事务前的状态
数据库支持两种事务模式:
自动提交模式:每个SQL语句都是一个独立的事务,数据库执行完一条SQL语句后,会自动提交事务。
手工提交模式:必须由数据库的客户程序显式指定事务的开始和结束边界
JDBC Connection类的事务控制方法:
setAutoCommit(boolean autoCommit) 设置是否自动提交事务,默认自动
commit() 提交事务
rollback() 撤销事务
Hibernate控制事务的方法:
1.调用sessionFactory不带参数的openSession方法,从连接池获得连接,Session自动把连接设为手工提交事务模式。
Session session = sessionFactory.openSession();
若调用带connection参数的openSession,则需要自己设置手工提交:
connection.setAutoCommit(false);
Session session = sessionFactory.openSession(connection);
2. 声明事务的开始边界
Transaction tx = session.beginTransaction();
3. 提交事务:tx.commit();
4. 撤销事务: tx.rollback();
注:
一个session可以对应多个事务,但是应优先考虑让一个session只对应一个事务,当一个事务结束或撤销后,就关闭session。不管事务成功与否,最后都应调用session的close关闭session任何时候一个session只允许有一个未提交的事务,不能同时开始两个事务。
二、缓存
Hibernate中提供了两级缓存,一级缓存是Session级别的缓存,它属于事务范围的缓存,该级缓存由hibernate管理,应用程序无需干预;二级缓存是SessionFactory级别的缓存,该级缓存可以进行配置和更改,并且可以动态加载和卸载,hibernate还为查询结果提供了一个查询缓存,它依赖于二级缓存;
1、缓存的概念
缓存是位于应用程序和永久性数据存储源之间用于临时存放复制数据的内存区域,缓存可以降低应用程序之间读写永久性数据存储源的次数,从而提高应用程序的运行性能;hibernate在查询数据时,首先会到缓存中查找,如果找到就直接使用,找不到时才从永久性数据存储源中检索,因此,把频繁使用的数据加载到缓存中,可以减少应用程序对永久性数据存储源的访问,使应用程序的运行性能得以提升;
2、缓存的范围
缓存范围决定了缓存的生命周期,缓存范围分为3类:
1、事务范围
缓存只能被当前事务访问,缓存的生命周期依赖于事务的生命周期,事务结束时,缓存的生命周期也结束了;
2、进程范围
缓存被进程内的所有事务共享,这些事务会并发访问缓存,需要对缓存采用必要的事务隔离机制,缓存的生命周期取决与进程的生命周期,进程结束,缓存的生命周期也结束了;
3、集群范围
缓存被一个或多个计算机的进程共享,缓存中的数据被复制到集群中的每个进行节点,进程间通过远程通信来保证缓存中数据的一致性;在查询时,如果在事务范围内的缓存中没有找到,可以到进程范围或集群范围的缓存中查找,如果还没找到,则到数据库中查询;
3、Hibernate中的第一级缓存
Hibernate的一级缓存由Session提供,只存在于Session的生命周期中,当应用程序调用Session接口的save()、update()、saveOrupDate()、get()、load()或者Query和Criteria实例的list()、iterate()等方法时,如果Session缓存中没有相应的对象,hibernate就会把对象加入到一级缓存中,当session关闭时,该Session所管理的一级缓存也会立即被清除;
4、Hibernate中的第二级缓存
二级缓存是一个可插拔的缓存插件,它是由SessionFactory负责管理的;由于SessionFactory对象的生命周期与应用程序的整个过程对应,通常一个应用程序对应一个SessionFactory,因此,二级缓存是进程范围或者集群范围的缓存;与一级缓存一样,二级缓存也是根据对象的id来加载与缓存,当执行某个查询获得结果集为实体对象集时,hibernate就会把它们按照对象id加载到二级缓存中,在访问指定的id的对象时,首先从一级缓存中查找,找到就直接使用,找不到则转到二级缓存中查找(必须配置且启用二级缓存),如果二级缓存中找到,则直接使用,否则会查询数据库,并将查询结果根据对象的id放到缓存中;
常用的二级缓存插件
Hibernate的二级缓存功能是通过配置二级缓存插件来实现的,常用的二级缓存插件包括EHCache,OSCache,SwarmCache和JBossCache。其中EHCache缓存插件是理想的进程范围的缓存实现,此处以使用EHCache缓存插件为例,来介绍如何使用hibernate的二级缓存;
5、Hibernate中的查询缓存
对于经常使用的查询语句,如果启用了查询缓存 ,当第一次执行查询语句时,hibernate会将查询结果存储在二级缓存中,以后再次执行该查询语句时,从缓存中获取查询结果,从而提高查询性能;hibernate的查询缓存主要是针对普通属性结果集的缓存,而对于实体对象的结果集只缓存id;查询缓存的生命周期,若当前关联的表发生修改,那么查询缓存的生命周期结束;
三、连接池
1、什么是数据库连接池?
官方:数据库连接池(Connection pooling)是程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由程序动态地对池中的连接进行申请,使用,释放。个人理解:创建数据库连接是一个很耗时的操作,也容易对数据库造成安全隐患。所以,在程序初始化的时候,集中创建多个数据库连接,并把他们集中管理,供程序使用,可以保证较快的数据库读写速度,还更加安全可靠。
2、数据库连接池的运行机制
1. 程序初始化时创建连接池
2. 使用时向连接池申请可用连接
3. 使用完毕,将连接返还给连接池
5. 程序退出时,断开所有连接,并释放资源