一.持久化对象概念
1. 就是数据库表对应的pojo类
2. 三种状态:
①瞬时态:(临时态,自由态) 一般指我们new 出来对象, 他不存在oid, 与我们hibernate session无关联,
不存在oid在数据库无记录,他使用完成后,会被JVM直接回收掉,只是用于信息携带;
②持久态 : 由hibernate session管理,具有持久化表示oid,他的特点,在事物未提交前,一直是持久态.
oid由session管理, 在数据库中数据有可能有,也可能没有,他发生改变时,hibernate能检测到.
③托管态:(也叫游离态,离线态), 持久太对象失去了session关联,存在oid,在数据库中有可能有,也可能没有
对于托管态对象,他发生改变时,hibernate不能检测到.
3.判断持久态对象三种状态: new 对象的时候就是瞬时态,无oid session.save(c) : 是持久态,生成策略生成id ,
比如:当session关闭, 就变成了游离态,但是还有oid;
4.三种状态的相互转换 :
瞬时态 -- -> 持久 save saveOrUpdate
瞬时态----->托管: 手动设置oid;(不建议)
持久态---> 瞬时 delete() 被删除或持久对象(不建议)
持久态---> 托管 session他的缓存就是一级缓存;清除一级缓存 evict(清除查询出的对象) clear(清空缓存)
close(关闭一级缓存)
托管态-->瞬时: 是无法直接获取,直接将oid删除;(不建议)
托管态-->持久态: update saveorupdate
5. hibernate 持久对象具有自动更新数据库的能力;查到一个对象, 改变对象的属性值, commit后,数据库会自动更改
一级缓存他底层使用一个map来存储, map的key 存储的是一级缓存对象, value存储的是快照(就是对象的属性)
当对象的属性改变时,一级缓存对象改变了,当session关闭,事物提交, 会判断一级缓存和快照是否一样,
如果不一样,他就会发送update语句;
二 hibernate缓存介绍:
一级缓存介绍:
1. hibernate的一级缓存指的是session缓存: 在session中定义一系列的集合来存储数据,他们构成了session缓存
只要session没有关闭,他就会一值存在;
2. 当我们通过hibernate中的session提供的API进行操作时,就会将持久化对象保存session中,当下一次在查询
缓存中具有对象(oid来判断), 就不会去数据库查询,直接从缓存中获取,
3. hibernate的一级缓存存在目的就是为了减少对数据库访问.
4.actionQueue 他是一行列队列,它主要记录crud操作的相关信息;
persistencecontext: 他是持久化上下文, 他是真正的session缓存;
5 一级缓存操作常用的API :
①.当我们通过session的save,update,saveorupdate操作时,如果缓存中没有,就会从数据库中查询到,
然后存到一级缓存中
②.session.clear; 清空一级缓存 , session.evict(c 查询出来的对象); 从一级缓存中删除一个指定的对象;
③ session.refresh(c 查询出来的对象);重新查询数据库, 用数据库里面数据来同步一级缓存和快照;
④update: 针对托管对象,持久对象具有自动更新能力.直接操作托管对象,他会将托管对象转为持久对象再操作;
如果session中出现相同的oid,会产生异常; 如果托管对象的oid不存在执行update,会产生异常;
⑤saveorupdate : 如果对象是一个瞬时对象----执行save操作, 如果是托管对象---执行update,
如果是持久对象他会自动去数据库更新;
⑥ delete: 删除一个托管对象,与session关联,再删除, 先删除一级缓存,再删除数据库;.
二级缓存: 他是sessionfactory级别缓存,人为指示缓存;
6. 很少被修改的数据,不是很重要的数据,允许出现偶尔并发的问题, 存储在硬盘中.
7.缓存插件: ehcache: 1. 导入jar包, 目录在 /源码/lib/ehcahe 三个jar包,
project/etc/ehcahe.xml 放在src下; eternal 缓存是否持久,
timetoidleseconds: 系统当机,是否保存到磁盘, tolive: 闲置n秒后销毁;
overflowtodisk: 内存中缓存达到最大上限,就缓存到硬盘.
8.在核心配置文件中, 1.开启二级缓存, 开启查询缓存, 配置二级缓存的regionfactory 配置哪些类需要缓存
三.hibernate关联查询
注意: 在两张表相互关联时,都写了tostring, 就会发生栈溢出
1.数据对象的三种关系;
一对一: 原则有两种, 唯一外键对应(在任意一方添加外键), 主键对应;
在设计实体类时候,分别在对方,添加对方的对象为成员属性;
一对多: 在数据库: 在多的一方添加外键列,
在类中:在多的那个类中添加对象为成员属性; 在一的那个类中添加一个集合
多对多: 添加第三张表,描述其对应关系. 在类中: 分别在对方类中的成员属性中,添加对象集合.
2. hibernate 关联映射
① 一对多,在多的hbm.xml中,
<many-to-one name="对象引用名称" class="全类名" column="外键名称">
在一的一方xml中, <set name="set集合名称"> <key column="外键自动名称"></key><one-to-man class="全类名">
注意: 一和多的的两边的column外键名称要一致;同样的有list,map标签, 多对多要在集合标签下面<many-to-many>
②测试单向保存,只保存订单,就会在两个表内添加数据.需要在订单配置文件中,
在<many-to-one cascade="save-update">,这样客户也会保存.保存客户时,保存订单,在 <set cascade="save-update">
③双向关联, 在配置要双向管理类. 可以通过任意一方来操作对方;
1. 在操作代码尽量不要进行双向关联, 比如: 客户添加了订单,订单就不用在添加哪个客户了. 会造成资源浪费;
2. 如果使用 双向关联,会存在多余的update语句,
解决: 在set标签上 inverse="turn" 是否反转 如果为true,由对方来维护外键, 反之,为本方维护;
外键在哪一个表中,就由谁维护;
④ 对象导航: 基于cascade, 两个表内都写了这个属性.根据关联的关系可以进行多条插入语句.
⑤删除订单,不需要删除客户,在set标签中 cascade="delete-orphan" 删除客户.需要删除订单. 在set标签中 cascade="delete"
3.使用cascade可以完成级联操作 , 它可常用取值: none这是一个默认值
save-update,当我们配置它时,底层使用save update或save-update完成操作,级联保存临时对象,如果是游离对象,
会执行update.
delete 级联删除
delete-orphan 删除与当前对象解除关系的对象。(删除孤儿)
注意:他们之间的区别: 删除孤儿,是当他是持久态的时候,查询出list集合,执行remove集合数据,他会更新到数据库
all 它包含了save-update delete操作
all-delete-orphan 它包信了delete-orphan与all操作
4.cascade与inverse有什么区别?
cascade它是完成级联操作,例如: 保存一方需要保存另一方
Inverse它只有在双向关联情况下有作用,它来指定由哪一方维护外键; 解决资源浪费;
四: 注解开发
1. po类注解配置:
@Entity //定义实体 @table(name="表名", catalog="库名")
@id 注解 @Generatedvalue(strategy=GenerationType.策略名) 不写参数是 默认的native
@column(name="数据库列名" ,length=30,nullable=true(是否为空)) @Temporal(TemporalType.日期类型)
如果成员属性没加注解,也会自动生成表中;列的名称就是属性名称
在核心配置文件中 <mapping class="全类名">
主键生成策略使用UUID类型; @GenericGenerator(name="myuuid",strategy="uuid")
@Generatedvalue(generator="myuuid")
如果不想要生成在表中成员属性: @Transient, 可以使用@type(type="属性类型"),在get方法上面也能使用以上注解
2.一对多的关系
① mappedby相当于inverse=true ,targetentity 相当于<one-to-many class=""> 中的class
@OneToMany(targetentity=对方.class , mappedBy="本方在对方成员属性引用名")
②@ManytoOne(targetentity=对方.class ) @joincolumn(name="外键列名称") //指定外键列
③保存客户保存订单, 在customer中配置
使用jpa提供注解 @OneToMany(cascade="")
在@OnetoMany注解下面: @cascade(cascadeType.注解类型);
@cascade 中的 delete-orphan 过时了, 在 @OneToMany(orphanmoval=true)
3. 注解: 多对多的关系 ,例子: .学生老师
① @ManytoMany 来配置多对多,只需要在一端配置中间表, 另一方mappeyby放弃外键维护权;
② @ManytoMany (targetentity=对方.class )
③使用jointable 描述中间表,并描述外键与student,teacher的映射关系 , name表名
joincolumns 他是用来本方与中间表的映射关系,inversesjoincolumns=对方表主键对应
jointable(name="",joincolumns={@joincolumn(name="")},inversesjoincolumns={@joincolumn(name="")})
④多对多级联删除: 前提:双向映射 两边都要有@cascade(all), 当删除一个数据时,他会找到另一个表,
但另一个表又会关联了两个表,所以会把所有数据删除.
4. 一对一关联关系 : 以人与身份证号
① 在任意一方,添加外键 @OnetoOne() @joincolumn(name="")
②主键映射 @Onetonone oprimarykeyjoincolumn 一边表配,
③ 在任何一方修改主键生成策略(name="my",strategy="foreign"
parameters={@paramter(name="property" vlaue="另一张表的引用名")})就是参考另一张表的主键
onetoone(mappedby="在另一张表中自己的引用名"
注意: 保存根据参考主键
五.hibernate 检索方式
1.导航对象图检索方式 : 通过在hibernate中进行映射关系,在hibernate操作时,可以用过导航方式得到,其关联的
持久化对象信息 ,支持链式编程
2.oid检索方式 : session.get() .load();
3.hql检索方式 最常用 :
①排序: from 类名 order by 类的成员属性 desc 默认asc
②条件检索: from 类名 where 类的成员属性>? session.setparameter(0,2000) 也可以使用setString()
......where 类的成员属性>:xc setparameter(xc,值);
③分页查询, setfirstresult(); setmaxresults();
④聚合: select count(*) from 表名
⑤分组: select from 表名 group by 成员属性中对方的引用名
⑥投影检索: 可以使用投影将部分属性封装到对象中。
提供相应的构造方法, select new 类名(name,id) from 类名
⑦多列查询: Select name ,address from Customer; 得到的是 List<Object[]>结果
⑧命名检索: 将hql语句先定义, session.getnamequery(hqlname);
1.如果有映射文件,那么当前hql是对哪一个实体进行操作.就在实体映射中,
<query name="myhql"> from 类名
2.使用注解来描述po的配置: 在类上面 @Namequery(name="myhql",query="from 类名 where name=?")
Query query = session.getNamedQuery("myHql");query.setentity(0,参数); 方法只有参数是实体的时候才能用
4.qbc检索方式 : 更加面向对象的检索方式.
①.通过session得到criteria对象 session.createcriteria(对象.class);
②设定条件 criteria实例 它的获取可以通过restrictons类提供静态,criteria的add方法用于添加查询条件判断
③调用list进行查询 criteria.list()
④排序 : criteria.addOrder(Order.desc("类的成员属性"))
⑤条件检索: criteria.add(restrictons.like("属性","张_")); lt< ge> le<= ge>= eq=
criteria.add(restrictons.and(restrictons.lt("属性","13432"),restrictons.eq("属性2","32"))
⑥分页检索: criteria.setfirstresult(这不是根据id来查的) criteria.setmaxresults();
⑦统计检索: criteria.setprojection(projections.rowcount()) sum,avg,rowcount统计总行
根据分组 criteria.setprojection(projections.projectionlist.add(projections.sum("money"))
.add(projections.groupproperty(""));
⑧离线查询: hibernate提供一个detachedcriteria对象,就可以在web层就将条件封装.在dao层就可得到criteria对象
1.在web阶段detachedcriteria.forclass(对象.class).add(restrictons.like("属性","张_"));
得到detachedcriteria对象, 把他的引用传递到dao层
2. 在dao层: dc.getexcutablecriteria(session).list();
5.本地SQL检索方式:
①createSQLquery(SQL语句);
②.本地SQL命名查询:
1. hbm.xml中 <sql-query name="自定义名">
2. 注解: @sqlresultsetmapping(name="自定义2",entities={@Entityresult(entitiyclass=类名.class,
fields={@fiedresult(name="",column="c_name"),....}) });类中的字段和表中的对应
@namednativequery(name="自定义名1" ,query="sql语句",resultsetmapping="自定义名2")
查询的结果集封装类型
session.getnamequery(自定义名1);