<1>web开发的层级结构:
a.概述:层与层之间存在自上而下的依赖关系,即上层组件会访问下层组件的API,而下层组件不应该依赖上层组件例如:表现层依赖于业务逻辑层,而业务逻辑层依赖于数据库层
每个层对上层公开API,但是具体的实现细节对外透明。当某一层的实现发生变化后,只要他的API不变,就不会影响到其他层。
b.软件分层的优点:
1)伸缩性:是指应用程序是否能支持更多的用户。应用的层越少,可以增加资源(如CPU和内存)的地方就越少,层数越多,可以将每层分布在不同的机器上
2)可维护性:当发生需求变化时,只需修改软件的某一部分,不会影响其他部分的代码
3)可扩展性:是指在现有系统中增加新功能的难易程度。层数越多,就可以在每层中提供扩展点,不会打破应用的整体框架
4)可重用性:是指程序代码没有冗余,同一个程序能满足多种需求。例如:业务逻辑层可以被多种表述层所共享
5)可管理性:是指管理系统的难易程度。将应用程序分为多层后,可以将工作分解给不同的开发小组,从而便于管理。应用越复杂,规模越大,需要的层就越多。
<2>软件开发的模型:真实世界的实体
软件开发的不同阶段,需要为目标系统创建不同类型的模型,
分析阶段:概念模型 用来模拟问题域中的真实实体,该模型描述了每个实体的概念和属性以及实体之间的关系,但并不描述实体的行为
关系数据模型:在概念模型的基础上建立起来的,用来描述这些关系数据的静态结构,由以下内容组成:
-一个或多个表
表的所有索引
视图
触发器
表与表间的参照完整性
设计阶段:域模型(面向程序) 面向对象的,在面向对象术语中也可称为设计模型,分为实体域对象(业务领域中的名词) 过程域对象(业务领域中的动词) 事件域(事件)
由以下内容组成:
具有状态和行为的域对象
域对象之间的关系----关联,聚集,依赖,一般化(泛化)
数据模型(面向数据库),两种模型需要映射
<3>JDBC API来持久化实体域对象:
java.sql包提供了JDBC API.在java.sql包中常用的接口和类包括:
1)DriverManager----驱动程序管理器,负责创建数据库连接。
2)Connection----代表数据库连接
3)Statement----负责执行SQL语句
4)PreparedStatement----负责执行SQL语句,具有预定义SQL语句的功能
5)ResultSet----代表SQL查询语句的结果集
缺点:
1)实现业务逻辑的代码和数据库访问代码掺杂在一起,使程序结构不清晰,可读性差
2)在程序代码嵌入面向关系的SQL语句,发生错误很难查找
3)数据修改相应的程序代码的所有SQL语句都需要修改,增加了维护软件的难度
<4>对象关系映射:ORM(Object-RelationShip mapping)模式---在单个组件中负责所有实体域对象的持久化,封装数据访问细节
ORM解决的主要问题就是对象-- 关系的映射。域模型和关系模型都分别建立在概念模型的基础上。域模型是面向对象的,而关系模型是面向关系的
一般情况下,一个持久化类和一个表对应,类的每个实例对应表中的一条记录
<5>java应用中使用Hibernate的步骤;
1)创建Hibernate的配置文件:src目录下的创建hibernate.cfg.xml配置文件,详细配置如下
小插曲:sqlserver 2000不能采用如下的配置,
应使用
2)创建持久化类:
持久化类符合javaBean的一般规范,包含一些属性以及与之对应的getter和setter方法
持久化类有一个id属性,用来惟一标识类的每一个对象,在面向对象术语中,这个id属性被称为对象标识符(OID,Object Identifier)
Hibernate要求持久化类必须提供一个不带参数的构造方法
3)创建对象关系映射文件:XXX.hbm.xm
番外篇:主键生成器
<generator>子元素用来设定标识符生成器。Hibernate提供了多种内置实现
<property>元素映射值类型属性
name属性---指定持久化类的属性的名字
type属性---指定Hibernate或java映射类型(Hibernate映射类型是Java类型与SQL类型的桥梁)
column属性---指定与类的属性映射的表的字段名
Hibernate配置文件的属性:
Hibernate API操纵数据库
4)通过Hibernate API编写访问数据库的代码
Hibernate框架的使用流程:
Hibernate首先通过Configuration的configure()方法,加载hibernate.cfg.xml,读取配置文件中的信息(因为只加载一次,因此对象与表的映射关系配置文件XXX.hbm.xml,
需要在hibernate.cfg.xml通过mapping标签引入),Configuration的configure方法,仍然返回Configuration对象,可以通过继续调用该对象的buildSessionFactory方法
创建SessionFactory,然后通过调用SessionFactory的openSession()方法,创建Sesion对象,针对于用户的每次请求都应创建不同的session对象,在session中开启
Transaction事务,在事务中进行相关的数据库操作,操作完毕以后调用session的close()方法,关闭session.
<6>Hibernate API
1)sessionFactory接口:
一个sessionFactory实例对应一个数据存储源,应用从SessionFactory中获得Session实例。拥有以下特点
a.线程安全的,它的同一个实例可以被应用的多个线程共享
b.重量级的,这意味着不能随意创建或销毁它的实例。如果应用只访问一个数据库,只需要创建一个SessionFactory实例,在应用初始化的时候创建该实例。如果应用
同时访问多个数据库,则需要为每个数据库创建一个单独的SessionFactory实例。
创建过程:因为它是重量级的,因此建议放到工具类的静态代码块中,只创建一次。如下图
2)session接口:
hibernate应用使用最广泛的接口,也被称为持久化管理器,它提供了和持久化相关的操作,如添加、更新、删除、加载和查询对象。拥有以下特点:
a.不是线程安全的,因此在设计软件架构时,应该避免多个线程共享同一个session实例。
b.轻量级的,所谓的轻量级是指它的创建和销毁不需要消耗太多的资源。这意味着在程序中可以经常创建和销毁session实例,例如为每个客户请求分配单独的session
实例,或者为每个工作单元分配单独的session实例。
此session非HttpSession(仅名称相同)
创建执行过程:
c.session中的get()与load()方法都可以获取相应的持久化对象,如果该对象存在那么两个方法的行为是一样的,如果该对象不存在,get返回null,load抛出异常
3)Transaction(事务):
JDBC获取connection,事务自动提交,需要setAutoCommit(false)
Hibernate的Transaction的实现就是将conn.setAutoCommit(false),使用上的提交回滚机制
4)Query:
a.对于分页操作来说,需要知道以下一些信息:当前正在操作的是第几页,每一页显示多少条记录数
b.对于Query接口的list()方法与iterator()方法来说,都可以实现获取查询的对象,但是list()方法返回的每个对象都是完整的(对象中的每个属性都被表中的字段填充上了)
而iterator()方法返回的对象仅包含了主键值(标识符),只有当对iterator()中的对象进行操作时,hibernate才会向数据库再次发送SQL语句来获取该对象的属性值 。
<7>HQL(Hibernate Query Language)----面向的是领域对象而不是数据库中的表,这是与SQL(Structured Query Language)之间的差别
<8>hbm配置文件详解:
1)映射一对多关联关系
一方的文件配置:one-to-many
cascade的属性值及其含义:
多方的文件配置:many-to-one
延迟加载:(Lazy Loading),在程序中获取到了一的一方,但是不需要多的一方,使用延迟加载是非常适合的。
如果需要的多的一方,有两种方式处理:
a.在session关闭前,使用多的一方,会使程序再发送一次请求,获取多的一方
b.在一对多的一方的配置文件中,加属性lazy="false"(取消延迟加载)
2)自身双向一对多映射关系:无限级的层叠关系如下图
3)一对一映射关系:
a.主键关联:两个表的主键值相同. 一对一默认使用的是立即加载,如果需要使用延迟加载,需要在one-to-one元素中的constrained属性设为true,fetch属性设为select,
并且将待加载的一方的 class元素中的lazy属性设为true(或者不去设置默认就为true);默认使用的是左外连接,可以通过修改fetch属性为select,修改成每次发送一
条sql语句的形式
配置文件:
Student类
IdCard类配置:
上图中fetch值为select 时打印的查询语句:
fetch值为join时打印的查询语句:
b.外键关联:一对多的特殊方式,在many-to-one元素中增加unique="true"属性一对多就变成了一对一,详细配置见下
4)多对多关系映射:两个一对多关系的映射(下图的配置为student与course的多对多关系的映射)
配置文件如下图图解所示,请按下图所示严格编写:
Student.hbm.xml的配置
Course.hbm.xml的配置
******##番外篇:域对象在持久化层的三种状态
Hibernate缓存:
Hibernate提供了两级缓存,第一级缓存是Session的缓存。由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务,因此它的缓存是事务范围的缓存
第一级缓存是必须的,不允许而且事实也无法被卸除。在第一级缓存中,持久化类的每个实例都有唯一的OID
a.session的缓存---一级缓存,不可更改
---session的缓存的作用
当session的save()方法持久化一个Customer对象时,Customer对象被加入到Session的缓存中,以后即使应用程序中的引用变理不再引用Customer对象,只要
Session的缓存还没有被清空,Customer对象仍然处于生命周期中
当session的load()方法试图从数据库中加载一个customer对象时,Session判断缓存中是否已经存在这个Customer对象,如果存在,就不需要再到数据库检索。
hibernate会保证缓存中的数据和数据库中数据的一致性。
session的get ()方法与load()方法的区别:
调用session的get ()方法,会从数据库查询,返回数据字段的所有值,即真实的对象。
调用session的load()方法,查询代理对象,只在session关闭之前,真正使用才回返回一条sql语句,返回所查询的对象
作用:
1)减少访问数据库的频率。应用程序从内存中读取持久化对象的速度显然比到数据库查询数据的速度快多了,因此session的缓存可以提高数据访问的性能;
2)保证缓存中的对象与数据库中的相关记录保持同步。当缓存中持久化状态发生了变化,Session并不会立即执行相关的SQL语句,这使得Session可以把几条相关的
SQL语句合并成一条SQL语句,以便减少数据库的访问性能,从而提高应用程序的性能。
---session清理缓存
清理缓存是指按照缓存中对象的状态的变化来同步更新数据库
---session清理缓存的时间
1)当应用程序调用org.hibernate.Transaction的commit ()方法时,commit()方法先清理缓存,然后再向数据库提交事务
2)当应用程序显示调用Session的flush()方法的时候
b.SessionFactory级别的缓存---二级缓存
第二级缓存是一个可插拔的缓存插件。它由SessionFactory负责管理。由于SessionFactory对象的生命周期和应用程序的整个进程对应,因些二级缓存是进程范围内的
缓存。这个缓存存放的是对象的散装数据。第二级缓存是可选 的,可以在每个类或每个集合的粒度上配置二级缓存。
---对象的临时状态、持久化状态和游离状态:
1)临时状态 (transient):刚刚用new语句创建,还没有被持久化,不处于Session的缓存中。处于临时状态的java对象被称为临时对象。与hibernate没有任何关系。
2)持久化状态(persistent):已经被持久化,加入到Session的缓存中。处于持久化状态的java对象称为持久化对象。已经和数据库表中某条记录相关联,有OID.
3 ) 游离状态(detached) :已经被持久化,但已不在Session的缓存中。处于游离状态的java对象称为游离对象。具有OID,与数据库表中某条记录相关联。
对象转换图:
例:Customer对象的状态转换过程:
---用session的update()方法使游离状态转化为持久化状态
1)把对象重新加入到缓存中,使其变为持久化对象
2)计划执行一个update语句,值得注意的是Session只有清理缓存时才会执行update语句,并且在执行时才会把对象的当前属性值组装到update语句中。因此
即使程序多次修改了对象的属性值,在清理缓存时只会执行一次update语句。
客户层与业务逻辑层之间传递临时对象和游离对象的过程:
hIbernate二级缓存深解:不需要写代码,只需要进行相应的配置
EhCache:针对于hibernate的一个插件
1)使用步骤:
a.在hibernate.cfg.xml配置文件中增加缓存配置
b.在相关领域对象的hbm配置文件中增加缓存配置
c.在工程的src目录下建立ehcache.xml配置文件
cache usage的取值有四个对应于数据库中的隔离级别:
b_1:transactional:必须在受管的环境下使用,保存可重复读的事务隔离级别,对于读/写比例大,很少更新的数据可以采取这种方式
b_2:read-write:使用timestamp机制维护已提交事务的隔离级别,对于读/写比例大,很少更新的数据可以采取这种方式
b_3:nonstrict-read-write:二级缓存可能与数据库存在不一致的情况。在使用这种策略时,应该设置足够短的缓存过期时间,否则就可能从缓存中读取到脏数据。
当一些数据很少改变,并且这些数据如果出现数据库与缓存不一致的情况影响并不大时,可以采取这种缓存策略。
b_4:read-only:每次都是从缓存中读取数据,因为设置为该属性时,数据库的数据是不会更改的,可以最大限度地优化数据库性能。
当确定数据不会更改时,可以采取这种配置。
<9>Hibernate的检索策略
1)立即检索策略
a.缺点:
a_1--select 语句的数目太多,需要频繁的访问数据库
,会影响检索性能。如需要查询n个customer对象,必须执行n+1次查询语句。这种检索策略没有利用SQL的
连接查询功能,使用SQL的左外连接查询功能,能够在一条select 语句中查询出CUSTOMERS表的所有记录,以及匹配ORDERS表的记录。
a_2--在应用逻辑只需要访问Customer对象,而不需要访问Order对象的场合,加载order对象完全是多余的操作,这些多余的ORDER对象浪费内存空间。
2)延迟检索策略--对于<set>元素,应该优先使用延迟检索策略
a.过程:
Customer对象的orders变量引用集合代理类实例,当应用程序第一次访问它,例如调用customer.getOrders().iterator()方法时,Hibernate会初始化这个集合代理
类实例,在初始化过程中到数据库检索所有与Customer关联的order对象
b.优点:
由应用程序决定需要加载哪些对象,可以避免执行多余的SQL语句,以及避免加载应用程序不需要的对象,提高检索性能,优化内存空间
c.缺点:
应用程序如果希望访问游离状态的代理实例,必须保证它以持久化状态进已经初始化
d.适用范围:
-- 一对多或者多对多的关联
--应用程序不需要立即访问或者根本不会访问的对象
3)左外连接检索策略:
默认情况下,多对一关联使用左外连接检索策略
在order.hbm.xml文件的<many-to-one>元素的outer-join属性设为true,总是使用左外连接检索策略
a.优点:
--对应用程序完全透明,不管对象处于持久化状态,还是游离状态,应用程序都可以方便的从一个对象导向到与它关联的对象
--使用了外连接, select语句减少
b.缺点:
--可能会加载应用程序不需要访问的对象,白白浪费许多的内存空间
--复杂的数据表连接会影响检索的性能
c.适用范围
--多对一或一对一关联
--应用程序需要立即访问的对象
--数据库系统具有良好的表连接性能
<10>Hibernate映射map关系:
1)map中的键值均是基本数据类型,配置文件如下:
2)map中的键值是object数据类型,配置文件如下:
a.包含map对象的领域对象的配置:team配置
b.map对象中的键所对应值的配置:student配置
<11>Hibernate映射Set与List
1)Set使用element子标签映射原子类型(string,date,int,long.....),即能够到数据库表字段的类型,而one-to-many映射的则是实体类型,指的是无法映射到表的某个字段,
而是要映射到整张表的类型,配置如下:(element与one-to-manty,many-to-many等元素是互斥的)
2)Hibernate映射List
<12>Hibernate映射bag:结合了List与Set,可以重复且没有顺序,由hibernate提供
<13>Hibernate对于查询数据的排序处理(内存排序及数据库排序)
1)数据库排序:使用order-by属性
a.map排序
对应的sql语句:
b.set排序
对应的sql语句:
2)内存排序:使用sort属性,与order-by均属于集合的属性,它有三个值 (unsorted,natural),其中natural指的是按照自然的升序排序。
第三个属性值是自定义的排序规则类:方式是定义一个类,让其实现Comparator接口,并且实现该接口中的compare方法,在该方法中实现排序规则即可。然后
将该自定义规则的全限定类名作为sort的属性值即可。
首先,自定义类型比较器,实现Comparator接口
在hbm文件中进行配置
<14>hibernate复合主键映射:
复合主键表所对应的实体类必须要实Serializable接口,对应的实体类必须要重写hashCode()和equals()方法
1)类中的每个属性都对应着数据表中的每个主键列。Hibernate要求具有联合主键的实体类实现Serializable接口,并且重写hashCode()和equals()方法,重写
这两个方法 的原因在于Hibernate要根据数据库的联合主键来判断某两行记录是否是一样的,如果一样那就认为是同一个对象,如果不一样,那么认为是不
同的对象。这反映到程 序领域中就是根据hashCode与equals方法来判断两个对象是否能放到诸如Set这样的集合当中。联合主键的实体类实现
Herializable的原因在于使用get或load方法的 时候需要先构建出来该实体对象,并且将查询依据(联合主键设置进去),然后作为get或load方法的第二个参数
传进去即可。
2)将主键所对应的属性提取出一个类(称之为主键类),并且主键类需要实现Serializable接口,重写equals方法和hashcode()方法,原因同上。
<15>组件映射:address类没有单独的数据库表与之对应,Address类中的两个属性对应的两个字段也存在于Student表中,配置文件如下
集合组件映射方式:
表结构:
<16>hibernate的继承映射:
1)每个子类一张表,每个子类对应一个hbm文件,在查询时采用多态查询,返回的都是父类类型的对象
2)一张表存储继承类的所有信息,表中字段是该继承体系中所有类的属性的并集,具体类在表中映射类中没有的字段则在表中的值置为空,造成表空间的浪费
配置文件以基类为主,需要在hbm文件增加如下的一个鉴别器
3)公共信息存储在父类表中,独有信息放在子类表中,每个子类对应一张表,保存与查询都涉及两张表
配置文件如下所示:
<17>hibernate检索对象的方式:
1)导航对象图检索方式:
根据已经加载的对象,导航到其他对象。例如,对于已经加载的customer对象,调用它的getOrders().iterator()方法可以导航到所有关联的order 对象,假如在关联级别中
使用了延迟加载策略,那么首次执行方法时,hibernate会从数据库加载关联的order对象,否则就从缓存中取得order对象
2)OID检索方式:
按照对象的OID来检索对象。Session的get()和load()方法提供了这种功能。如果应用程序事先知道了OID,就可以使用这种方式。
3)HQL检索方式:
hiberante提供了Query接口,它是hibernate提供的专门的HQL查询接口,能够执行各种复杂的HQL查询语句。
a.步骤:
a_1:通过session的createQuery()方法创建一个Query对象,它包含一个HQL查询语句。HQL查询语句可以包含命名参数
a_2:动态绑定参数.Query接口提供了各种类型的命名参数赋值的方法。
a_3:调用Query的list()方法执行查询语句。该方法返回List类型的查询结果。在List集合中存放了符合查询条件的持久化对象,如果返回的是唯一确定结果的对象,
可以通过使用uniqueResult()方法,返回唯一对象。可以使用方法链的编程风格
4)QBC检索方式:
使用QBC(Query By Criteria)API来检索对象,这种API封装了基于字符串形式的查询语句,提供了更加面向对象的接口。
a.检索方式:
b.检索步骤:
b_1:调用Session的createCriteria()方法创建一个Criteria对象
b_2:设定查询条件。Expression类提供了一系列用于设定查询条件的静态方法,这些静态方法都返回Criterion实例,每个Criterion实例都代表一个查询条件。
Criteria的add方法用于加入查询条件。
b_3:调用Criteria的list()方法执行查询语句。该方法返回List类型的查询结果,在List集合中存放了符合查询条件的持久化对象。对于上图中的程序代码,当运行
Criteria的list()方法时,hibernate执行的查询语句:
select * from CUSTOMERS where name like 'T%' and AGE=21
方法链的编程风格如下图:
分页查询:
Query和Criteria都提供了用于分页显示查询结果的方法
----setFirstResult(int firstResult):设定从哪一个对象开始检索,参数firstResult表示这个对象在查询结果的索引位置,索引位置的起始值是0.默认情况下,Query和
Criteria接口从查询结果中的第一个对象,也就是索引位置为0的对象开始检索。
----setMaxResult(int maxResults):设定一次最多检索出的对象数目。默认情况下,Query和Criteria接口检索出查询结果的所有对象。
代码模板:
HQL查询:
实体类作为query查询参数的设置参数方式:
Session的过滤功能:session.createFilter(Object collection,String queryString)
QBC查询:
排序:
<19>数据库的事务与并发处理:
1)数据库事务的概念:
事务(Transaction)--是指一组相互依赖的操作行为,事务的成功取决于这些相互依赖的操作行为是否都能执行成功。它体现出整体的概念,要么事务中的操作全部成功,
要么全部失败。数据库的事务是对现实生活中事务的模拟,它由一组业务逻辑上相互依赖的SQL语句组成。
2)数据库事务的生命周期:
3)声明事务的边界:
a.事务的开始边界:beginTransaction
b.事务的正常结束边界(commit):提交事务,永久保存被事务更新后的数据库状态
c.事务的异常结束边界(rollback):撤销事务,使数据库退回到执行事务前的初始状态
4)数据库事务的4个特性:
a.原子性(Atom):事务中包含的程序作为数据库的逻辑工作单位,它所做的对数据修改操作要么全部执行,要么完全不执行。
b.一致性(Consistance):在一个事务执行之前和执行之后数据库都必须处于一致性状态
c.隔离性(Isolation):一个事务内部的操作及正在操作的数据必须封锁起来,不被其它企图进行修改的事务看到。
d.持久性(Duration):系统或介质发生故障时,确保已提交事务的更新不能丢失。即一旦一个事务提交,DBMS保证它对数据库中数据的改变应该是永久性的,耐得住任何系
统故障。持久性通过数据库备份和恢复来保证。
5)通过JDBC API声明事务边界:
Connection提供了以下用于控制事务的方法
---setAutoCommit(boolean autoCommit):设置是否自动提交事务
---commit():提交事务
---rollback():撤销事务
6)通过Hibernate API声明事务边界:
---声明事务开始的边界:Transaction tx=session.beginTransaction();
---提交事务:tx.commit();
---撤销事务:tx.rollback();
7)多个事务并发运行时的并发问题:
---第一类丢失更新:撤销事务时,把其他事务提交的更新数据覆盖
---脏读:一个事务读到另一个事务未提交的更新数据
---虚读:一个事务读到另一个事务已提交的新插入数据
---不可重复读:一个事务读到另一个事务已提交的更新数据
---第二类丢失更新:不可重复读的特例。一个事务覆盖另一个事务已提交的更新数据
8)事务隔离级别:
9)隔离级别与并发性能的关系:隔离级别越高,并发性能越低
10)设定隔离级别的原则:
---隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能影响也越大
---对于多应用程序,可以优先考虑把数据库系统的隔离级别设为Rean Commited,它能够避免脏读,而且具有较好的关发性能。尽管它会导致不可重复读、虚读和第二类
更新这此并发问题,在可能出现这些问题的个别场合,可以由应用程序采用悲观锁和乐观锁来解决
11)Hibernate设置隔离级别:
在hibernate的配置文件可以显示地设置隔离级别,每个隔离级别都对应一个整数
---1.Read Uncommited
---2.Ream Commited
---4.Repeatable Read
---8.Serializable
在hibernate.cfg.xml通过hibernate.connection.isolation=2类似于这样的配置设置隔离级别,对于从数据库获取得每个连接,Hibernate都会把它改为使用
Read Commited隔离级别。
12)悲观锁:所有用户对数据库的操作都可能会出现并发问题,都是由底层数据库控制,在程序开发中很少使用
14)乐观锁:是由应用程序控制的一种机制 ,这种机制既能保证多个事务并发访问数据库,又能防止第二类丢失更新问题
在应用程序中,可以利用hibernate提供的版本控制功能来实现乐观锁。对象-关系映射文件中的<version>元素和<timestamp>元素都具有版本控制功能
-<vesion>元素利用一个递增的整数来跟踪数据库表中记录的版本
-<timestamp>元素利用时间戳来跟踪数据库表中记录的版本
1)通过使用version配置乐观锁,解决并发问题
a.在领域对象中添加version属性,并为其添加getter和setter方法,生成相应的表时会添加version列,其类型为integer
b.在领域对象对应的hbm文件中,作如下的配置:
利用<version>元素进行版本控制,当hibernate更新一个对象时,会根据它的id与version属性到相应的表中寻找匹配的记录,如果存在匹配的记录就更新记录,并且修
改version字段的值,找不到匹配的记录时,hibernate会抛出StaleObjectStateException.在应用程序中应该捕获该异常,这种异常有两种处理方式:方式1--自动撤销该
事务,需要重新开始事务。方式2:--通知用户信息已经被其他事务修改,由用户决定如何继续事务,用户也可以决定立刻撤销事务。
2)通过使用timestamp来配置时间锁
a.在领域对象中添加date类型的字段,并生成相应的getter和setter,生成相应的表时表中会添加该字段,其值不需要手动修改
(备注:针对于SqlServer 需要设置类型为timestamp)
b.在领域对象对应的hbm文件作如下的配置:
<20>hibernate的拦截器和事件:
1)拦截器 (Interceptor):
a.实现:可以直接实现Interceptor接口,也可以继承EmptyInterceptor,通常使用后者
b.分类:
---Session范围内
---SessionFactory范围内
c.步骤:
---定义实现拦截器接口Interceptor的实现类
---通过session启用拦截器或者通过Configuration启用全局拦截器
当使用某个重载SessionFactory.openSession()使用Interceptor作为参数调用打开一个session时,就指定了一个session范围内的拦截器
2)事件系统:
可以使用Hibernate3的事件框架,响应持久层的某些事件。该事件系统可以用来替代拦截器,也可以作为拦截器的补充来使用。
基本上,Session接口的每个方法都有相对应的事件。比如LoadEvent,FlushEvent,等等(可以查阅XML配置文件的DTD以及org.hibernate.event包来获得所有
已定义的事件)。
步骤:
--定义自定义拦截器类
--在hibernate.cfg.xml配置文件进行事件配置
<21>hibernate的主键生成器:org.hibernate.id包的下属类来实现
<22>hibernate数据库连接池(Connection Pool):C3P0,Apache.DBCP 必须要实现javax.sql.DataSource接口
1)JNDI(Java 命名与目录接口)通过名字获取访问对象
2)hibernate默认采用的是C3PO数据库连接池,可以在hibernate.cfg.xml进行配置,也可以不配置采用默认配置,建议不配置。