Hibernate学习笔记

Hibernate运行过程

1、初始化配置
Configuration cfg = new Configuration()
* cfg.config() // 加载类路径下的默认配置文件hibernate.cfg.xml
* cfg.config("xxx/xxx/xxx/hibernate.cfg.xml") // 加载指定路径下的配置文件
* 加载Bean映射文件XXXBean.hbm.xml
* 将映射文件配置在hibernate.cfg.xml文件中
<mapping resource="cn/pzchen/test/start/Customer.hbm.xml"/>
* 使用cfg.addClass(XXXBean.class)添加

2、创建SessionFactory
* SessionFactory sessionFactory = cfg.buildbuildSessionFactory()

3、创建Session
* Session session = sessionFactory.openSession();

4、开启事务
* Transaction tx = session.beginTransaction();

5、事务操作
* session.save()
* session.update()
* session.delete()
* session.get()
* .....
6、事务提交
* tx.commit()


Hibernate知识点

1、设置派生属性
利用<property>元素的formula属性,用来设置一个sql表达式,hibernate将根据它来计算出派生属性的值。
<property name="sum" type="integer" formula="(select count(*) from customer c)" />
注意:formula属性的值要用“()”括起来

2、Hibernate中持久化类的访问者有两个(从保存和查询两条路线看) 
* Hibernate在保存对象时是通过对象的JavaBean的getXXX方法获取取对象属性,并进行数据库持久化操作
* Hibernate在进行查询时是通过对象的JavaBean的setXXX方法将查询的数据赋值到相应的对象中

3、session快照
* Hibernate在进行对象的保存和查询时,会首先将要保存和查询出来的对象先放入其一级缓存中,同时将对象的
值放在session的快照中一份,此时再没执行commit之前,所有对对象的修改都会触发产生update的操作,从而
将对象更新
// 放到session的一级缓存中
session.save(c);
// 更新快照,产生update语句,在未提交之前
c.setName("ttttt");

Hibernate: insert into customer (name) values (?)
Hibernate: update customer set name=? where id=?

* Hibernate在进行对象更新时,也会首先将要更新的对象放入一级缓存,在没有执行commit之前均可对将要更新
的对象进行修改

4、Hibernate联合主键配置
* Hibernate的联合主键对象需要实现Serializable接口,并且要重写equals和hashCode方法
* Hibernate联合主键配置
<composite-id name="comId" class="cn.pzchen.test.compk.CompositeId">
<key-property name="firstName" column="firtname" type="string"/>
<key-property name="lastName" column="lastname" type="string"/>
</composite-id>

5、Hibernate再做资源文件映射时,不能将表名属性设置成sql的关键字否则会报,例如表名不能为order
org.hibernate.exception.SQLGrammarException: could not insert: [cn.pzchen.test.many2one.Order]


6、多对一 (订单和客户)订单一方
订单order配置
* cascade="save-update" 属性表示关联父对象,级联保存和更新
慎用
<many-to-one name="customer" class="cn.pzchen.test.many2one.Customer" cascade="save-update" not-null="true">
<column name="Id" not-null="true" />
</many-to-one>
* 再更新订单信息要特别要注意关联
1、 要这么做
Order o = new Order();
o = (Order) session.get(Order.class, 3);
o.setOrderDes("ttttttttttt");
session.update(o);

2、 不可这么做
Order o = new Order();
o.setOrderDes("ttttttttttt");
session.update(o);

* 如果先对多的一方进行保存时,例如先对订单进行保存,然后再保存用户,hibernate将产生三条sql语句:
Hibernate: insert into orders (orderDes, Id) values (?, ?)
Hibernate: insert into customer (name) values (?)
Hibernate: update orders set orderDes=?, Id=? where orderId=?
而此时如果只保存订单不保存用户,则会报错异常如下:
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: cn.pzchen.test.many2one.Customer
由于Hibernate默认情况下只对自己的对象具有持久化能力,不会对关联的对象也进行持久化,此时可以通
过在mapping文件中增加cascade="save-update"属性就可以让Hibernate对关联对象也进行持久化

如果先保存用户在保存订单此时,Hibernate会产生两条sql语句,如下:
Hibernate: insert into customer (name) values (?)
Hibernate: insert into orders (orderDes, Id) values (?, ?)

7、 多对多的配置:
多的一方:
<many-to-one name="customer" class="cn.pzchen.test.many2one.Customer" not-null="true">
<column name="Id" not-null="true" />
</many-to-one>
一的一方:
<set name="orders">
<key>
<column name="Id"></column>
</key>
<one-to-many class="cn.pzchen.test.many2many.Order"/>
</set>

8、session中的方法
flush: 进行清理缓存(此时缓存中的数据并不丢失)的操作,让缓存和数据库同步 执行一些列sql语句,但不提交事务,;
     
      commit:先调用flush() 方法,然后提交事务. 则意味着提交事务意味着对数据库操作永久保存下来。
     
      reresh:刷新,让session和数据库同步,执行查询,把数据库的最新信息显示出来,更新本地缓存的对象状态.
     
      clear:清空缓存,等价于list.removeAll();
     
session缓存的清理模式
* FlushMode.AUTO(默认)  session的查询方法都会清理、tx的commit方法清理、session.flush清理
* FlushMode.COMMIT不清理 清理 清理
* FLushMode.NEVER不清理 不清理清理

清理session的缓存(设置缓存的清理模式)
FLushMode.NEVER 应用大批量操作插入10万记录

session缓存的清理在进行批量添加时,要控制好清理时机,清理之后要进行clear操作,否则有可能会出现内存溢出的异常
java.lang.OutOfMemoryError: Java heap space内存溢出

9、get和load的区别
        * 当查询的id所对应的记录不存在时:
* get得到的结果为null
* load则会抛出异常
* get总是立即查询(检索)
* load可以通过配置使其立即查询和延迟查询
  
10、Hibernate对象四种状态
* 持久态
* OID 不为 null
* 位于 Session 缓存中
* 持久化对象和数据库中的相关记录对应
* Session 在清理缓存时, 会根据持久化对象的属性变化, 来同步更新数据库
* 在同一个 Session 实例的缓存中, 数据库表中的每条记录只对应唯一的持久化对象

* 临时态
* 在使用代理主键的情况下, OID 通常为 null
* 不处于 Session 的缓存中
* 在数据库中没有对应的记录


* 游离态
* OID 不为 null
* 不再处于 Session 的缓存中
* 一般情况需下, 游离对象是由持久化对象转变过来的, 因此在数据库中可能还存在与它对应的记录

使用session的close方法可以将缓存中的对象都清空,如何还有变量引用之前session缓存中的对象,此时该对象即为游离态的
使用session的evict方法可以将缓存中的对象变成游离态的

* 删除态
* OID 不为 null
* 从一个 Session实例的缓存中删除
* Session 已经计划将其从数据库删除, Session 在清理缓存时, 会执行 SQL delete 语句, 删除数据库中的对应记录
一般情况下, 应用程序不该再使用被删除的对象

Session 的特定方法能使对象从一个状态转换到另一个状态
    
11、Session中的查询策略

类级别:
get方法: 属于类级别的立即检索
load方法:在lazy = true时:延迟检索 等于false是位立即检索此时和get意义相同

query接口查询时:不管是lazy等于false或者true都是立即检索    

关联级别:set集合,即多对一关系中一的一端
fetch: join/select/subselect
lazy: true/false/extra
load/get方法测试 类级别为lazy = false
* 使用fetch=join、lazy=false组合时:迫切左外连接
* 使用fetch=join、lazy=true组合时:迫切左外连接
* 使用fetch=join、lazy=extra组合时:迫切左外连接

load/get方法测试 类级别为lazy = false
* 使用fetch=select、lazy=false组合时:立即检索
* 使用fetch=select、lazy=true组合时:延迟检索
* 使用fetch=select、lazy=extra组合时:增强延迟检索

load/get方法测试 类级别为lazy = false
* 使用fetch=subselect、lazy=false组合时:立即检索
* 使用fetch=subselect、lazy=true组合时:延迟检索
* 使用fetch=subselect、lazy=extra组合时:增强延迟检索

query方法测试 类级别为lazy = false
* 使用fetch=join、lazy=false组合时:立即检索
* 使用fetch=join、lazy=true组合时:延迟检索
* 使用fetch=join、lazy=extra组合时:增强延迟检索

query方法测试 类级别为lazy = false
* 使用fetch=select、lazy=false组合时:立即检索
* 使用fetch=select、lazy=true组合时:延迟检索
* 使用fetch=select、lazy=extra组合时:增强延迟检索

query方法测试 类级别为lazy = false
* 使用fetch=subselect、lazy=false组合时:立即检索,采用子查询
* 使用fetch=subselect、lazy=true组合时:延迟检索,子查询
* 使用fetch=subselect、lazy=extra组合时:增加延迟检索

关联级别:<many-to-one>,多对一关系中多的一端
fetch: join/select
lazy: false/proxy/no-proxy

load/get方法测试 类级别为lazy = false
* 使用fetch=join、lazy=false组合时:迫切做外连接
* 使用fetch=join、lazy=proxy组合时:迫切做外连接
* 使用fetch=join、lazy=no-proxy组合时:迫切做外连接

load/get方法测试 类级别为lazy = false
* 使用fetch=select、lazy=false组合时:立即检索
* 使用fetch=select、lazy=proxy组合时:
如果一的一端类级别lazy=false 则立即检索
如果一的一端类级别lazy=true 则延迟检索

query方法测试 类级别为lazy = false
* 使用fetch=join、lazy=false组合时:立即检索
* 使用fetch=join、lazy=proxy组合时:立即检索

query方法测试 类级别为lazy = false
* 使用fetch=select、lazy=false组合时:立即检索
* 使用fetch=select、lazy=proxy组合时:
如果一的一端类级别lazy=false 则立即检索
如果一的一端类级别lazy=true 则延迟检索

12、many2one立即检索+set立即检索组合如何配置
many2one一端
fecth="select", lazy="false"
set一端
fecth="select", lazy="false"

13、many2one迫切左外+set立即检索组合如何配置
many2one一端
fecth="join", lazy="false"
set一端
fecth="select", lazy="false"

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值