hibernate 技术介绍

一、 What?
Hibernate是一种ORM工具,是连接 java 应用程序和关系数据库的中间件,主要负责 java 对象的持久化操作。是JDBC的轻量级实现,在应用程序和数据库之间架起了一条映射的桥梁。(映射是通过配置文件来维护的)



二、 Why?
对象持久化的概念:
把内存中的数据转存到外部持久设备
对象持久化的原因:
1. 内存不能长时间的保留数据
2. 内存容量有限
3. 需要数据共享
4. 业务需要数据能够格式转化,支持数据检索
5. 使用hibernate的原因
1) 使用hibernate,应用程序层就可以专注于业务逻辑的实现,只需要知道怎么使用hibernate 所提供的接口,而不用知道具体实现的细节。
2) 封装了JDBC之后,就可以连接数据库时减少代码的冗余。
3) 直接用映射文件,可以方便的实现与不同数据库连接。
三、 How?
编程步骤:
(1) 配置环境,将Hibernate所使用的包导入到工程中。
(2) 写POJO类:包括主键、属性、实例变量、无参的构造器、set/get方法,还可以提供一个有参的构造方法供我们使用。提供无参的构造方法是因为在Hibernate中,它会用反射机制去实例化这个类的对象。
(3) 写配置和映射文件:
hibernate.cfg.xml的配置:参见hibernate.cfg.xml
hibernate的实体类XXX映射文件XXX.hbm.xml的配置:参见Users.hbm.xml
(4) 调用Hibernate的API编程
A. Configuration config = new Configuration();
B. SessionFactory factory =config.configure().buildSessionFactory();
调用configure()方法解析hibernate.cfg.xml配置文件,创建SessionFactory,然后通过解析这个文件来建立与特定数据的连接。并且从里面的mapping-resource 里面配置的文件,来进行关系影射。
SessionFactory是线程安全的,可以被多线程调用以取得Session,而且构造它很消耗资源,所以多数情况下一个应用中只初始化一个SessionFactory,为不同的线程提供Session。
C. Session session=factory.openSession();
Session是Hibernate运作的中心,对象的生命周期、事务的管理、数据库的存取都与Session息息相关。Session不是线程安全的,多个执行线程共享一个Session,将会发生数据共享而发生混乱问题。为了解决此问题,可以采用ThreadLocal变量,使用它可以有效隔离执行所使用的数据,也就避开了Session的多线程之间的数据共享问题。
D. Transaction trans = session.beginTransaction();
E. 通过session对象操作数据库
session.delete();
     session.save()
session.saveOrUpdate()
     session.update()
     session.load();
F. Transaction.commit();
G. 关闭资源
4、 hibernate对象状态转换
(1) session机制
A. 原理:
Session中维护一个缓冲区。在对象进入持久化状态时,同时在session缓冲区中保存一个这个对象的副本,当刷新缓冲的时候,会将这个副本和内存的对象进行比较,如果发现有不同,则进行同步。
B. 好处:
a) 减少数据库的访问频率,提高访问性能。
b) 保证缓存中的对象与数据库同步,位于缓存中的对象称为持久化对象。
c) 当持久化对象之间存在关联时,Session 保证不出现对象图的死锁。
Session同时也是事务范围内的缓存,除了对自动乐观并发控制提供版本管理,针对行级悲观锁定,Hibernate也提供了辅助的API操作
C. 同步时机:
Session默认情况下自动同步的时机:
a) commit() 方法被调用时
b) 显示的调用session 的 flush方法
c) 查询时会清理缓存,保证查询结果能反映对象的最新状态
D. Session同步时机的设置:
FlushMode.AUTO: 默认的,在以上三个时候都会刷新
FlushMode.COMMIT:只有当提交或者明确调用flush()时
FlushMode.NEVER:只有明确调用flush()方法时,才刷新。
(2) 对象的状态转换
参见:对象在hibernate状态转换.doc
6、 基数类型的对象关系映射
(1) 一对一映射
A. 唯一外键
如:一个订单(order)只有一个送货地址(address)
本质上是一个一对多的双向关联,只是在多的一方用unique限制
参见:one-to-one文件夹下的
User-fk.hbm.xml
Account-fk.hbm.xml
B. 共享主键
参见:one-to-one文件夹下的
User.hbm.xml
Account.hbm.xml
使用注意:
a) 对于作为外键同时是主键的那个影射文件,它的ID的生成方式必须是foreign。
b) Constrained(约束)表明该类对应的表和被关联的对象所对应的表之间,通过一个外键引用对主键进行约束。这个选项影响save()和delete()在级联执行时的先后顺序,到了hibernate 3.0之后是可选的,可写可不写。
c) 延迟加载:想要在one to one 关系中实现延迟加载。仅有lazy=”true”是不够的,还需要加上constrainted=“true”;才能实现。
(2) 一对多
应用场合:一个类中的某个属性,是另外一个类的集合。
参见one-to-many文件夹
使用注意:
在一对多的双向关联关系中,关系的维护都应该由多的一方维护,所以在一的那方把inverse 属性设为true(即在<set>标签中设置inverse=”true”)。在数据库操作的时候,可以执行较少的语句,从而能够提高效率。否则在有外键的一方总是先插入一条语句,然后再执行update()操作,才能完成真正的插入。
(3) 多对多
如:一个学生可以选多门课程,一门课程可以由多个学生选择。
参见:many-to-many文件夹
使用规则:
A. 在多对多关系关系中,都是双向关联,那么双方关系的维护放在任何一方都可以。
B. Inverse:可以放在任意一方,但是不能两边都放,否则中间表就没有关联上。
C. 在删除的时候,如果两放的cascade=“save-update”,那么就不能删除inverse=”true”方。
D. 双方不能同时cascade=”all”,要不删除任意一方的时候,都会把两个表以及关联表中的数据都删掉。
E. 如果inverse=”true”所在的级联关系是cascade=“save-update”,另一方是cascade=“all”,那么双放就都不可以删除。
F. 如果inverse=”true”所在的级联关系是cascade=“all”,另一方是cascade=“save-update”,那么删除inverse=”true”所在的放一方,就会同时把中间表和另一方表的内容删掉。
总结一句话就是:
在多对多的映射是,删除的时候,尽量不要删除inverse=”true”所在的一方,同时两边的关联关系都设置为save-update”,其他的关系,在删除的时候都会出问题(不能删除,或者删除的时候跟业务逻辑不符合)
7、 组件关系映射
(1) 单一组件映射
如:一个小汽车一个引擎
参见:component文件夹下的Car.hbm.xml
A. 使用场合:两个类之间的关联关系比较强烈,并且附属对象的属性比较少,且冗余少的情况。
B. 优点:只需要建一张表,只需要写一个配置文件。查询效率高。
(2) 集合组件映射
参见:component文件夹下的Account.hbm.xml
A. 使用场合:一对多关系强烈,附属类的属性都是基本属性,并且不需要维护到主类之间的关系,不是一个独立的实体类(也即对应的表没有主键oid,但是有外键来约束主类的主键)
B. 数据库特点:集合组件映射,只用一个表
C. 一对多关系强烈时候的首选

8、 继承关系映射
(1) 一个类写一张表,包括父类
A. 特点:子类和父类各自对应自己的一张表。
B. 优点:
很好的遵循了面向对象的思想,支持多态查询,只需要在合适的表中拥有角色所需要的字段即可。修改继承树中的父类和子类都很容易,因为只需要修改一个类或一个表。
C. 缺点:
a) 有太多的数据表,每张表对应一个类(在多对多关系中还需要用一张额外的表去维护关系);
b) 查询的时候要多表join查询,效率低。
D. 使用场合:需要多态且子类属性较多的时候适用
E. 配置文件片段;
<joined-subclass name="DebitAccount" table="inhreit_all_debit">
<key column="oid"></key>
<property name="currency" column="currency" not-null="true"></property>
</joined-subclass>
(2) 整个继承层次所有类一张表
A. 特点:子类和父类都在同一张表中,支持多态查询 ,
B. 缺点:会有大量的null字段,并且子类的属性不能有非空限制。
C. 优点:只使用一个表,查询时只需一次简单的sql语句,查询效率高。
D. 使用场合:需要多态且子类属性较少的时候适用。
E. 配置文件片段
<subclass name="CreditAccount" discriminator-value="c">
<property name="credit" column="credit" ></property>
</subclass>
(3) 一个具体子类建一张表
A. 特点:即父类没有表,每一个子类单独对应一个表,不支持多态查询,操作时只对单表
B. 缺点:修改父类的时候,其具体的子类所对应的表字段也都要随之改变;不支持多态,一个支持多角色,则保持数据完整性很困难。
C. 优点:简单易用,因为一个具体类只存在一张表中。
D. 配置文件片段:
<union-subclass name="CreditAccount" table="entity_creidt">
<property name="credit" column="" not-null="true"></property>
</union-subclass>
9、 值类型的集合映射
(1) Set:无序、不可重复
<set name="值类型集合属性名" table="表名">
<key column="外键字段名" />
<element type="值类型的映射类型名--如:string"
column="值类型的单值对应的字段名" />
</set>
(2) Bag:无序、可重复
<idbag name="值类型集合属性名" table="表名">
<collection-id column="集合主键字段名-cid">
<generator class="主键产生方式- increment" />
</collection-id>
<key column="外键字段名" />
<element type="值类型的映射类型名--如:string"
column="值类型的单值对应的字段名" />
</idbag>
(3) List:可重复、有顺序
<list name="值类型集合属性名" table="表名">
<key column="外键字段名" />
<list-index column="保存List下标的字段名" />
<element type="值类型的映射类型名--如:string"
column="值类型的单值对应的字段名" />
</list>
(4) Map:键值对
<map name="值类型集合属性名" table="表名">
<key column="外键字段名" />
<map-key column="保存Map键值的字段名" />
<element type="Map值类型的映射类型名--如:string"
column="Map值对应的字段名" />
</map>
10. 其他一些知识点
(1) HQL
面向对象的查询语言,里面的查询目标是对象,判断条件是类的属性。
A. 等值查询
from Account(类名) a where a.bal(类属性)=?
B. 模糊查询(like 查询)
from Account a where a.actno like act-00%;
C. 范围查询(in 查询)
List params =new ArrayList();
parames.add(“ “);
from Account a where a.actno in (:actlist);
query.setParameterList(params);
D. 做报表查询的语句
select new day05.NamePair(s.name,c.name) from Student s join s.cours c;
注:day05.NamePair是自己定义的一个VO(value object);要加上包名。
E. 其他查询,大于、小于、or等都跟sql语句是一样的。
(2) 锁机制:
A. 悲观锁:
事务一访问一个数据的时候,别的事务不能进行任何操作,实际上第二个事务不一定存在,只是第一个事务悲观的一种想象。牺牲了效率来达到数据安全的目的。
B. 乐观锁
在读取数据库中数据的时候,把读取的数据加上版本号,往数据库里面存的时候,只有当数据库中版本号小于要插入数据的版本号的时候,才能操作成功。需要在pojo对象里面加一个version属性,在对应的数据库表中加一个version字段,配置文件中也需要配置。
(3) inverse:(确定关系维护者)
A. Inverse=“true”:把双方关系的维护交给对方,否则自己维护。主要用在一对多,和多对多关系中。
B. 在一对多的关系中,把关系维护交给多的一方,即在一的一方,设置:inverse=”true”;
C. 在多对多的关系中,随便哪方都可以:但是不能同时都设置。
D. 主要目的是:在插入记录的时候,直接就执行了Insert语句,而不用先插入空,再执行update语句。提高了执行效率
(4) Cascade: (设置级联属性)
A. save -update:两个对象在存储和修改的时候级联。主要应用于一对一,一对多关系中一的一方。
B. delete:只要有级联关系,那么删除一个对象的时候,删除所有与之有级联关系的对象。
C. all:所有操作(delete和save-update),都有级联。
D. delete-orphan:删除所有和当前对象解除关联关系的对象。
E. all-delete-orphan:两个类之间有父子关系(即父亲不存在了,儿子的存在已经没有意义了,主要用于从集合中删除对象的情况。包含all和delete-orphan两个要求。
(5) lazy=”true” (延迟加载,默认就是true)
A. 本质:延迟加载,只取需要的,提高效率。
B. 例如:User 中有一个集合属性Account,在表结构中,二者是有关联关系得两个表,那么当调用session.load(student)/get(student) 方法时,只是先把User这条记录取出,而Account 的取出,则在第一次使用的时候才加载。
C. 注意:在一对一主键关联的时候,还需要配合constraited=”true”来共同实现延迟加载。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值