Hibernate持久层操作

来源:互联网 发布:专科出国读研 知乎 编辑:程序博客网 时间:2024/05/01 15:21

1,数据加载

1),Session.get/load
区别:(1),未发现符合条件的记录:get-->null,load-->ObjectNotFoundException。
(2),load可返回实体的代理类实例,get永远直接返回实体类。
(3),load-->内部缓存-->二级缓存-->SQL(DB),get-->内部缓存-->SQL(DB)。

Session加载实体对象时经过的过程:
内部缓存(查找数据)-->NonExists(查找查询条件)-->第二级缓存(load方法)-->Select SQL(DB)-->根据Result创建对应的数据对象-->将其数据对象纳入当前Session实体管理容器(内部缓存)-->执 行Interceptor.onLoad-->纳入二级缓存-->如果数据对象实现了LifeCycle接口,则调用数据对象的onLoad 方法-->返回数据对象。

2),Session.find/iterate
Session.find()------->session.createQuery().list()-----无法利用缓存,它对缓存只写不读。
Session.iterate()---->session.createQuery().iterate()-----可以充分利用缓存。
-------基于充分利用缓存以提升性能上的考量。
内存使用上的考虑:对海量数据进行操作,find方法一次获得所有的记录并将其读入内存-->内存消耗甚至OutOfMemoryError。
解决方案之一:逐条对记录进行处理,将内存消耗保持在可以接受的范围之内。
String hql = "from TUser where age > ?";
Iterator it = session.iterate(hql,new Integer(18),Hibernate.INTEGER);
while(it.hasNext()){
TUser user = (TUser)it.next();
session.evict(user);//将对象从一级缓存中移除
sessionFactory.evict(TUser.class,user.getId());//将对象从二级缓存中移除
}
解决方案之二:SQL或存储过程。

3),Query Cache
---中保存了之前查询操作执行过的Select SQL,以及由此查询产生的查询结果集(包括查询对象的类型和id)。

根据查询SQL--->从Query Cache中检索--->取出这个SQL的检索结果集--->根据这个结果集中对象类型及其id,从缓存中取出对赢得实体对象返回。

Query Cache只在特定的情况下产生作用:
(1),完全相同的Select SQL重复执行。
(2),在两次查询之间,此Select SQL对应的库表没有发生过改变。

<hibernate-configuration>
<session-factory>
....
<property name="hibernate.cache.use_query_cache">true</property>
....
</session-factory>
<hibernate-configuration>

String hql="from TUser where age > ?";
Query query = session,createQuery(hql).setInteger(0,20);
query.setCacheable(true);

List userList = query.list();
int len = userList.size();
for(int i=0;i<len;i++){
TUser user = (TUser)userList.get(i);
}

query = session2.createQuery(hql).setInteger(0,20);
query.setCacheable(true);//第二次查询时,也必须将Cacheable设为true

userList = query.list();
len = userList.size();
for(int i=0;i<len;i++){
TUser user = (TUser)userList.get(i);
}
看到第二次查询时,Hibernate并没有执行任何Select SQL即完成了任务,这就是Query Cache的作用。

4),延迟加载(Lazy Loading)
---为了避免在某些情况下,关联关系所带来的无谓的性能开销。---即在需要数据的时候,才真正执行数据加载操作。

Hibernate2延迟加载实现主要针对:(1),实体对象;(2),集合。
Hibernate3同时提供了属性的延迟加载功能。

(1),实体对象的延迟加载
<class ... laze="true"> ---Hibernate2中,laze属性默认为false,Hibernate3中其默认值为true。
Hibernate的代理机制:Hibernate中引入了CGLib作为代理机制实现的基础。CGLib可以在运行期动态生成Java Class,这里的代理机制,其基本实现原理就是通过由CGLib构造一个包含目标对象所有属性和方法的动态对象(相当于动态构造目标对象的一个字类)返 回,并以之作为中介,为目标对象提供更多的特性。真正的TUser对象位于代理类的CGLIB$CALLBACK_0.target属性中。
-----只有当客户程序真正调用实体类的取值方法时,Hibernate才会执行数据库查询操作。

(2),集合类型的延迟加载
<set ... lazy="true">
Hibernate.initialize方法可以强制Hibernate立即加载关联对象集。
Hibernate.initialize(user.getAddresses());
session.close();
//通过Hibernare.initialize方法强制读取数据,addresses对象即可脱离session进行操作
Set hset = user.getAddresses();
TAddress addr = (TAddress)hset.toArray()[0];

(3),属性的延迟加载
<property ... lazy="true">
与实体和集合类型的延迟加载不同,Hibernate3属性延迟加载机制在配置之外,还需要借助类增强器对二进制Class文件进行强化处理。

5),数据保存

Session.save方法用于实体对象到数据库的持久化操作。
包含步骤:在Session内部缓存中寻找待保存对象-->lifecycle(onSave())-->Validatable (validate())-->Interceptor.onSave()-->构造Insert SQL-->user.id=new id-->将user对象放入内部缓存-->对级联关系进行递归处理。

Session.update:根据待更新实体对象的Key在当前session的内部缓存中进行查找(一个Persistent实体对象调用update并不会产生作用)-->初始化实体对象的状态信息(作为之后脏数据检查的依据),并将其纳入内部缓存。

Session.saveOrUpdate:实际上是save和update方法的组合应用,它本身并没有增加新的功能特性,但是却为我们的应用层开发提供了一个相当便捷的功能选择。--无需关心传入的user参数到底是怎样的状态。
public interface IUserDAO{
public TUser getUser(String id);
public void saveUser(TUser user);
}

6),数据批量操作

(1),数据批量导入
<session-factory>
...
<property name="hibernate.jdbc.batch_size">25</property>
...
</session.factory>

public void importUserList() throws HibernateException{
Transaction tx = session.beginTransaction();
for(int i=0;i<10000;i++){
TUser user = new TUser();
user.setName("user" + i);
session.save(user);

if(i%25==0){ //以每25个数据作为一个处理单元
session.flush();
session.clear();
}
}
tx.commit();
}

(2),数据批量删除

内存消耗:
Transaction tx = session.beginTransaction();
String hql = "from TUser";
Query query = session.createQuery(hql);
ScrollableResults scRes = query.scroll();
while(scRes.next()){
TUser user = (TUser)scRes.get(0);
session.delete(user);
}
tx.commit();

迭代删除操作的执行效率:采用调整hibernate.jdbc.batch_size参数来解决。

BULK delete/update:
Transaction tx = session.beginTransaction();
String hql = "delete TUser";
Query query = session.createQuery(hql);
int ret = query.executeUpdate();
tx.commit();
--------批量删除与缓存管理的矛盾仍然存在。---关闭二级缓存,调用不同session解决内部缓存带来的问题。

7),Collection

(1),Collection类型(org.hibernate.collection)
无序集:Set,Bag,Map
有序集:List
---无序与有序,是针对Hibernate数据持久过程中,是否保持数据集合中的记录排列输序加以区分的。

Set:
陷阱--->
<set name="addresses" table="t_address" lazy="false">
<key column="user_id"/>
<one-to-many class="TAddress"/>
</set>
<set name="addresses" table="t_address" lazy="false">
<key column="user_id"/>
<element type="string" column="address"/>
</set>

Bag:允许包含重复元素的“Set”。---基于List但屏蔽其有序性。
idbag:
<idbag name="addresses" lazy="true" table="t_address">
<collection-id type="int" column="id">
<generator class="identity"/>
</collention-id>
<key column="user_id">
<element type="string" column="address"/>
</idbag>

Map:键值对应关系。
<map name="addresses" lazy="true" table="t_address">
<key column="user_id"/>
<index type="string" column="type"/>
<element type="string" column="address"/>
</map>
index:要求在数据集中取值唯一。
TUser user = (TUser)session.load(TUser.class,new Integer(1));
user.getAddresses().get("Home");//读取家庭地址
user.getAddresses().get("Office");//读取办公地址

List:实现了集合内元素顺序的持久化。
<list name="addresses" lazy="true" table="t_address">
<key column="user_id"/>
<index type="integer" column="idx"/>
<element type="string" column="address"/>
</list>

8),结果集排序
排序强调的是针对现有数据,以特定的逻辑对其排列此序进行调整,而排序的结果,是数据在内存中的某种排列次序,属于临时状态。

排序方式:
Sort--->Collection中的数据排序,如对一个List中的元素先后进行排序调整。(JVM)
<set ... sort="natural".../>
如果期望指定某种特殊的排序算法,那么可以实现java.util.Comparator接口,如:
package org.sample
public class LengthComparator implements Comparator{
public int compare(Object obj1,Object obj2){
String str1 = String.valueOf(Obj1);
String str2 = String.valueOf(Obj2);
return str1.length()-str2.length();
}
}
<set ... sort="org.sample.LengthComparator".../>
---Bag,List不支持sort排序方式。

order-by--->对数据库执行Select SQL时,由order by子句实现的数据排序方式。(数据库)
<set ... order-by="address desc".../>
List不支持order-by排序。

 
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 鼻子老是流清水鼻涕怎么办 5岁儿童感冒鼻塞怎么办 3岁宝宝感冒鼻塞怎么办 宝宝9个月流鼻涕怎么办 鼻涕又黄又粘稠怎么办 鼻子一直流黄水怎么办 宝宝眼屎多又黄怎么办 宝宝痰多鼻涕多怎么办 小孩痰多鼻涕多怎么办 用qq登不了微博怎么办 中国银行u盾丢了怎么办 我的世界遇见him怎么办 考军校年龄超了怎么办 dnf组队就红电脑怎么办 九阳高压锅漏气怎么办 晋江买了防盗章怎么办 开车撞了人应该怎么办 开车撞了人没钱怎么办 驾照扣分12分后怎么办 车被交警拖走了怎么办 符石耐久没了怎么办 冒险岛2老是掉线怎么办 冒险岛老是掉线怎么办 冒险岛2延迟高怎么办 高速超速扣6分怎么办 优酷视频有密码怎么办 斗鱼直播很卡怎么办 鼠标的滑轮坏了怎么办 宝马1系烧机油怎么办 原房主不迁户口怎么办 做假账被发现了怎么办 裆部潮湿有异味怎么办 用了开塞露还是拉不出大便怎么办 安卓模拟器很卡怎么办 锁屏图案忘了怎么办 手机图案锁忘了怎么办 炸东西油变黑了怎么办 自热米饭吃完后怎么办 无线网密码忘了怎么办 普通税票开错了怎么办 发票购买本丢了怎么办