web应用开发知识之hibernate(4)

一 基本概念

1 DAO: 数据访问对象(Data Access Object DAO)可以说是一种设计模式,用于将低级别的数据访问逻辑与高级别的业务逻辑分离

 

2 ORM:对象关系映射,是一种将对象与关系数据库表相映射的技术,实现java持久化对象与数据库二维关系的转换,以及对数据库连接,事务等的管理.ORM解决的主要问题就是对象关系映射:比如类与关系,对象与记录,属性与字段 之间的对应关系

 

3 hibernate:是采用ORM模式实现数据持久层的一个优秀的java组件,是连接java应用程序和关系数据库的中间件,它封装了JDBC,可以对java对象进行持久化,可以进行数据库连接管理及事务的管理

 

二 OID生成器:如increment,identity,uuid.hex...;

 

(1)Hibernate使用对象标识符(OID)来建立内存中的对象和数据库中记录的对应关系,对象的OID和数据库表的主键对应

(2)通常OID对应数据库表的代理主键,自然主键(具有业务含义的字段),如用户自定义的NAME;而代理主键不具备业务含义的字段,该字段一般取名为“ID”。

(3)为了保证持久化对象的OID的唯一性和不变性,通常由Hibernate或底层数据库来给OID复值。因此,可以把持久化类的OID的setId()方法设置为Private类型以禁止Java应用程序随便修改OID;而把getId()方法设为public类型,使得Java应用程序都可以读取持久化对象。在对象关系映射文件中,<id>元素用来设置对象标识符,例如:

  1. <id name="id"  type="long" column="ID">  
  2.      <generator class="increment"/>  
  3. </id> 

 

在使用代理主键的情况下,setId()是无效的,OID的生成器有以下几种:

 

三 Hibernate核心API:

 

(1)Configuration接口,用来装载hibernate.cfg.xml配置文件,以及获得SessionFactory接口对象 

 

(2)SessionFactory接口,通常一个SessionFactory实例对应于一个数据源,它是一个重量级实例(包括数据库配置及映射关系),创建时开锁较大,在使用时应考虑重用已建立的SessionFactory实例,所以SessionFactory被设计为线程安全的;通常如果应用程序只访问一个数据库,则只需要创建一个SessionFactory实例就可以了,如果应用程序要同时访问多个数据库,则需要为每个数据库创建一个单独的SessionFactory实例

 

(3)Session接口,封装Connection对象,他还提供了对数据持久化对象进行操作的方法,可以把它想象成一个持久对象的缓冲区,Hibernate能够自动检测缓冲区中的持久化对象是否已经改变,并及时刷新数据库,以保证Session中的对象与数据库同步;它不是线程安全的,意味着一个session实例只能被一个线程使用;session实例是轻量级的,即它的创建和销毁不需要占用太多的资源,我们可以为每个客户请求分配单独的session实例

 

四 hibernate缓存机制相关

参考: http://www.cnblogs.com/xiaoluo501395377/p/3377604.html

 

1 缓存种类

(1)一级缓存,即Session级别缓存,用于缓存实例对象,它是内置的,不能被卸载,一级缓存也称事务级缓存. 当要清理缓存时,可以调用session.evict() 方法,注意要确保先调用session.flush()方法将缓存中的内容同步到数据库中

 

(2)二级缓存,即SessionFactory级别缓存

  • EHCache: 是针对每个实例类的缓存机制,可以配置存储路径,对象的数量,是否允许存储,在内存的存活时间等等.
  • 一般二级缓存配置为read-only,因为可写要对数据的修改加并发同步机制,更新缓存,会让程序性能变差,所以应当在不需要进行修改的实体类上使用 二级缓存,当数据库的数据与缓存的不同步时,缓存中的数据就变成了脏数据,这个问题要通过对象在缓存中的生存时间配置来降低使用脏数据的风险
  • 二级缓存不会缓存HQL查询语句的结果
  • sessionFactory也有evict() 方法和flush()方法

 

(3)查询缓存,

  • 一级缓存和二级缓存都只是存放实体对象的,如果查询实体对象的普通属性的数据,只能放到查询缓存里,查询缓存还存放查询实体对象的id。
  • 查询缓存要求查询语句包括参数全部相同才的效
  • 当查询的是实体对象时,查询缓存缓存的也是ID,所以一定要开启二级缓存 ,缓存内容才能跨session共享,不然了会出现n+1的情形
  • 查询缓存的生命周期不确定,就是说查询缓存和session的生命周期没有关系,查询缓存也session缓存也没有依赖关系.当它关联的表发生修改,查询缓存的生命周期就结束。这里表的修改指的是通过hibernate修改,并不是通过数据库客户端软件登陆到数据库上修改
  • 查询缓存意义不大,查询缓存说白了就是存放由list方法或iterate方法查询的数据。我们在查询时很少出现完全相同条件的查询,这也就是命中率低,这样缓存里的数据总是变化的,所以说意义不大。除非是多次查询都是查询相同条件的数据,也就是说返回的结果总是一样,这样配置查询缓存才有意义。

 

2 Query.list()与Query.iterator的区别:

 

(1)list(): 在没有配置查询缓存的情形下,每次调用list()都会向数据库发出查询,不会使用session一级缓存,这样会使内存消耗得快

 

(2)iterator(): 首先发出一条查询语句,查询对象的id列表,然后根据缓存情况,决定 是否发出更多的查询语句,来查询对象数据, 这样容易出现n+1问题(指在查询对象数据的时候,发出了n+1条查询语句)

 

(3)结合使用: 如果我们需要在一个session当中要两次查询出很多对象,此时我们如果写两条 list()时,hibernate此时会发出两条 sql 语句,而且这两条语句是一样的,但是我们如果第一条语句使用 list(),而第二条语句使用 iterator()的话,此时我们也会发两条sql语句,但是第二条语句只会将查询出对象的id,所以相对应从缓存取出所有的对象而已,显然这样可以节省内存,减少也数据库的交互次数

 

5 load()与get(): 

(1)对于get方法,hibernate会确认一下该id对应的数据是否存在,首先在session缓存中查找,然后在二级缓存中查找,还没有就查数据库,数据库中没有就返回null

(2)对于load方法, 首先查询session缓存,没有就创建代理,实际使用数据时才查询二级缓存和数据库,如果确定数据一定存在,那么可以使用load方法来实现延迟加载

(3)总之对于get和load的根本区别,一句话,hibernate对于load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,如果在使用过程中发现了问题,只能抛org.hibernate.ObjectNotFoundException异常;而对于get方法,hibernate一定要获取到真实的数据,否则返回null。

(4)如果加载一个对象是为了访问它的属性,用get; 如果是为了删除它,或是建立与别的对象的关联,则可用load

(5)org.hibernate.LazyInitializationException异常: 当对一个映射类的配置使用延迟加载策略时,加载一个对象时不会把他的关联对象的数据加载进内存,而是当使用这个关联对象时才加载,当在session关闭后才使用这个关联对象时,就会抛出这个异常,解决办法是将延迟加载属性设为false.

 

 

五 对象关系映射配置:

 

1 在关系数据库中,只存在主键参照关系,并且总是从多方参照到一方,即是在多方表中引用一方的主键作为外键,这样就能消除数据冗余,所以关系数据库实际上只支持多对一的单向关联关系:当主外键方都为one时,多对一的单向关联也就变为了一对一的单向关联了

参考: http://book.51cto.com/art/201001/178868.htm

 

关系分析模型: 用O代表oder,用C代表customer

 

st1: 1个O对应1个C,而1个C对应0到N个O,那么可以表示如下:

O   0..N---◇---1   C

 

st2: 从O到C是 多对一 关系,O将C依赖(符合关系表的表示,数据不冗余):

O   0..N---◇---1-->   C

 

st3: 从C到O是1对多关系,C将O的列表依赖(不符合二维关系表的表示,因为数据冗余):

O   <--0..N---◇---1   C

 

st4: 两者结合起来是: 不但O将C依赖,而且C也将O的列表依赖(也不符合二维关系表的表示,因为数据冗余)

 

映射对象的状态 

 

hibernate对分布式事务支持:

一般是要结合Spring和第三方jta实现才能支持分布式事务,注意Tomcat也没有实现JTA

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值