Hibernate的强制加载策略

推迟加载:

推迟加载机制是号码大全为了防止一些无谓的功用开支而提出来关键词挖掘工具的,所谓推迟加载即是当在真实需求数据的时分,才真实履行数据加载操作。在Hibernate中供给了对实体方针的推迟加载以及对调集的推迟加载,另外在Hibernate3中还供给了对特点的推迟加载。下面咱们就别离介绍这些品种的推迟加载的细节。

A、实体方针的推迟加载:

假如想对实体方针运用推迟加载,有必要要在实体的映射装备文件中进行相应的装备,如下所示:

?

……

经过将class的lazy特点设置为true,来敞开实体的推迟加载特性。假如咱们运转下面的代码:

User user=(User)session.load(User.class,”1”);(1)

System.out.println(user.getName());(2)

当运转到(1)处时,Hibernate并没有建议对数据的查询,假如咱们此刻经过一些调试东西(比方JBuilder2005的Debug东西),调查此刻user方针的内存快照,咱们会惊奇的发现,此刻回来的可能是User$EnhancerByCGLIB$$bede8986类型的方针,并且其特点为null,这是怎么回事?还记得前面我曾讲过session.load()办法,会回来实体方针的署理类方针,这儿所回来的方针类型即是User方针的署理类方针。在Hibernate中经过运用CGLIB,来完结动态结构一个方针方针的署理类方针,并且在署理类方针中包含方针方针的一切特点和办法,并且一切特点均被赋值为null。经过调试器显现的内存快照,咱们能够看出此刻真实的User方针,是包含在署理方针的CGLIB$CALBACK_0.target特点中,当代码运转到(2)处时,此刻调用user.getName()办法,这时经过CGLIB赋予的回调机制,实践上调用CGLIB$CALBACK_0.getName()办法,当调用该办法时,Hibernate会首先查看CGLIB$CALBACK_0.target特点是不是为null,假如不为空,则调用方针方针的getName办法,假如为空,则会建议数据库查询,生成相似这样的SQL句子:select * from user where id=’1’;来查询数据,并结构方针方针,并且将它赋值到CGLIB$CALBACK_0.target特点中。

这样,经过一个中心署理方针,Hibernate完结了实体的推迟加载,只要当用户真实建议获得实体方针特点的动作时,才真实会建议数据库查询操作。所以实体的推迟加载是用经过中心署理类完结的,所以只要session.load()办法才会运用实体推迟加载,由于只要session.load()办法才会回来实体类的署理类方针。

B、调集类型的推迟加载:

在Hibernate的推迟加载机制中,对于调集类型的运用,含义是最为严重的,由于这有可能使功用得到大幅度的提高,为此Hibernate进行了很多的尽力,其间包括对JDK Collection的独立完结,咱们在一对多相关中,定义的用来容纳相关方针的Set调集,并不是java.util.Set类型或其子类型,而是net.sf.hibernate.collection.Set类型,经过运用自定义调集类的完结,Hibernate完结了调集类型的推迟加载。为了对调集类型运用推迟加载,咱们有必要如下装备咱们的实体类的对于相关的有些:

…..

经过将元素的lazy特点设置为true来敞开调集类型的推迟加载特性。咱们看下面的代码:

User user=(User)session.load(User.class,”1”);

Collection addset=user.getAddresses();      (1)

Iterator it=addset.iterator();               (2)

while(it.hasNext()){

Address address=(Address)it.next();

System.out.println(address.getAddress());

}

当程序履行到(1)处时,这时并不会建议对相关数据的查询来加载相关数据,只要运转到(2)处时,真实的数据读取操作才会开端,这时Hibernate会依据缓存中契合条件的数据索引,来查找契合条件的实体方针。

这儿咱们引入了一个全新的概念——数据索引,下面咱们首先将讲一下啥是数据索引。在Hibernate中对调集类型进行缓存时,是分两有些进行缓存的,首先缓存调集中一切实体的id列表,然后缓存实体方针,这些实体方针的id列表,即是所谓的数据索引。当查找数据索引时,假如没有找到对应的数据索引,这时就会一条select SQL的履行,获得契合条件的数据,并结构实体方针调集和数据索引,然后回来实体方针的调集,并且将实体方针和数据索引归入Hibernate的缓存之中。另一方面,假如找到对应的数据索引,则从数据索引中取出id列表,然后依据id在缓存中查找对应的实体,假如找到就从缓存中回来,假如没有找到,在建议select SQL查询。在这儿咱们看出了另外一个疑问,这个疑问可能会对功用产生影响,这即是调集类型的缓存战略。假如咱们如下装备调集类型:

…..

这儿咱们运用了装备,假如选用这种战略来装备调集类型,Hibernate将只会对数据索引进行缓存,而不会对调集中的实体方针进行缓存。如上装备咱们运转下面的代码:

User user=(User)session.load(User.class,”1”);

Collection addset=user.getAddresses();

Iterator it=addset.iterator();

while(it.hasNext()){

Address address=(Address)it.next();

System.out.println(address.getAddress());

}

System.out.println(“Second query……”);

User user2=(User)session.load(User.class,”1”);

Collection it2=user2.getAddresses();

while(it2.hasNext()){

Address address2=(Address)it2.next();

System.out.println(address2.getAddress());

}

运转这段代码,会得到相似下面的输出:

Select * from user where id=’1’;

Select * from address where user_id=’1’;

Tianjin

Dalian

Second query……

Select * from address where id=’1’;

Select * from address where id=’2’;

Tianjin

Dalian

咱们看到,当第2次履行查询时,履行了两条对address表的查询操作,为啥会这样?这是由于当第一次加载实体后,依据调集类型缓存战略的装备,只对调集数据索引进行了缓存,而并没有对调集中的实体方针进行缓存,所以在第2次再次加载实体时,Hibernate找到了对应实体的数据索引,可是依据数据索引,却无法在缓存中找到对应的实体,所以Hibernate依据找到的数据索引建议了两条select SQL的查询操作,这儿造成了对功用的糟蹋,怎样才能防止这种状况呢?咱们有必要对调集类型中的实体也指定缓存战略,所以咱们要如下对调集类型进行装备:

…..

此刻Hibernate会对调集类型中的实体也进行缓存,假如依据这个装备再次运转上面的代码,将会得到相似如下的输出:

Select * from user where id=’1’;

Select * from address where user_id=’1’;

Tianjin

Dalian

Second query……

Tianjin

Dalian

这时将不会再有依据数据索引进行查询的SQL句子,由于此刻能够直接从缓存中获得调集类型中寄存的实体方针。

C、特点推迟加载:

在Hibernate3中,引入了一种新的特性——特点的推迟加载,这个机制又为获取高功用查询供给了有力的东西。在前面咱们讲大数据方针读取时,在User方针中有一个resume字段,该字段是一个java.sql.Clob类型,包含了用户的简历信息,当咱们加载该方针时,咱们不得不每一次都要加载这个字段,而不论咱们是不是真的需求它,并且这种大数据方针的读取自身会带来很大的功用开支。在Hibernate2中,咱们只要经过咱们前面讲过的面功用的粒度细分,来分化User类,来解决这个疑问(请参照那一节的论述),可是在Hibernate3中,咱们能够经过特点推迟加载机制,来使咱们获得只要当咱们真实需求操作这个字段时,才去读取这个字段数据的才能,为此咱们有必要如下装备咱们的实体类:

……

经过对元素的lazy特点设置true来敞开特点的推迟加载,在Hibernate3中为了完结特点的推迟加载,运用了类增强器来对实体类的Class文件进行强化处置,经过增强器的增强,将CGLIB的回调机制逻辑,参加实体类,这儿咱们能够看出特点的推迟加载,仍是经过CGLIB来完结的。CGLIB是Apache的一个开源工程,这个类库能够操作java类的字节码,依据字节码来动态结构契合要求的类方针。依据上面的装备咱们运转下面的代码:

String sql=”from User user where user.name=’zx’ ”;

Query query=session.createQuery(sql);   (1)

List list=query.list();

for(int i=0;i  User user=(User)list.get(i);

System.out.println(user.getName());

System.out.println(user.getResume());   (2)

}

当履行到(1)处时,会生成相似如下的SQL句子:

Select id,age,name from user where name=’zx’;

这时Hibernate会检索User实体中一切非推迟加载特点对应的字段数据,当履行到(2)处时,会生成相似如下的SQL句子:

Select resume from user where id=’1’;

这时会建议对resume字段数据真实的读取操作。

---------------------------------

推迟加载的方针:

hibernate 2对于实体方针和调集

hibernate 3一起供给了特点的推迟加载功用。

其间对调集的推迟加载特性含义最为严重。

实体方针的推迟加载:

1.在hibernate装备文件中的class指定

调集类型的推迟加载:

在set中指定lazy=true

这样只要实践加载与方针相相关的调集方针的时分,再经过session从数据库中加载实践的数据集。

Hibernate.initialize办法能够强制Hibernate当即加载相关的方针集,例如:

Hibernate.initialize(user.getAddress());

调集类型的缓存:

假如为某个调集类设定了缓存,如

name="address"

table="t_address"

lazy="true"

......

>

Hibernate对调集类型进行缓存的时分,分两有些保留。首先是这个调集中一切实体的id列表,其次才是各个实体方针。

这儿制定了cache usage="read-only"只会使得Hibernate对数据索引进行缓存。也即是说只缓存了调集中的数据索引,并不包含调集中的各个实体元素。

假如指定cache usage="read-write"才会对调集中的实体进行缓存。

特点的推迟加载:

在property节点中声明lazy=true,并且还需求凭借Hibernate类增强器对POJO类的二进制Class文件进行强化处置。

hibernate的推迟加载通用办法

public class HibernateUtil extends HibernateDaoSupport {

//用法:instance =  getHibernateTemplate().find("from FxjlbVO");

//    super.initialize(instance, "getFxjlbChjs");

public void initialize(Object object, String methodName)

throws SecurityException, NoSuchMethodException,

IllegalArgumentException, IllegalAccessException,

InvocationTargetException {

String[] methodArray = methodName.split("/.");

Method method = null;

Object initializeObject = object;

if (methodArray.length == 1) {

this.getHibernateTemplate().lock(initializeObject,

org.hibernate.LockMode.NONE);

method = object.getClass()

.getMethod(methodArray[0], new Class[] {});

initializeObject = method.invoke(initializeObject, new Object[] {});

this.getHibernateTemplate().initialize(initializeObject);

} else {

for (int i = 0; i < methodArray.length; i++) {

method = initializeObject.getClass().getMethod(methodArray[i],

new Class[] {});

initializeObject = method.invoke(initializeObject,

new Object[] {});

}

this.getHibernateTemplate().lock(initializeObject,

org.hibernate.LockMode.NONE);

this.getHibernateTemplate().initialize(initializeObject);

}

}

public void initialize(Object object, String methodName[])

throws SecurityException, NoSuchMethodException,

IllegalArgumentException, IllegalAccessException,

InvocationTargetException {

for (int i = 0; i < methodName.length; i++) {

String[] methodArray = methodName[i].split("/.");

Method method = null;

Object initializeObject = object;

if (methodArray.length == 1) {

this.getHibernateTemplate().lock(initializeObject,

org.hibernate.LockMode.NONE);

method = object.getClass().getMethod(methodArray[0],

new Class[] {});

initializeObject = method.invoke(initializeObject,

new Object[] {});

//等价于:initializeObject=PropertyUtils.getProperty(initializeObject,methodArray[0]);

this.getHibernateTemplate().initialize(initializeObject);

} else {

for (int j = 0; j < methodArray.length; j++) {

method = initializeObject.getClass().getMethod(

methodArray[j], new Class[] {});

initializeObject = method.invoke(initializeObject,

new Object[] {});

}

this.getHibernateTemplate().lock(initializeObject,

org.hibernate.LockMode.NONE);

this.getHibernateTemplate().initialize(initializeObject);

}

}

}

// fInitializeFields是调调集,不是办法名

//instance =  getHibernateTemplate().find("from FxjlbVO");

//    HashSet aa=new HashSet();

//    aa.add("fxjlbChjs");

//    super.initialize(instance, aa);

public void initialize(Object object, HashSet fInitializeFields)

throws SecurityException, NoSuchMethodException,

IllegalArgumentException, IllegalAccessException,

InvocationTargetException {

String[] methodName = new String[fInitializeFields.size()];

methodName = (String[]) fInitializeFields.toArray(methodName);

for (int i = 0; i < methodName.length; i++) {

String[] methodArray = methodName[i].split("/.");

Method method = null;

-        indexRead arguments from command-line "http://www.shoudashou.com"

-        indexRead arguments from command-line "http://www.4lunwen.cn"

-        indexRead arguments from command-line "http://www.zx1234.cn"

-        indexRead arguments from command-line "http://www.penbar.cn"

-        indexRead arguments from command-line "http://www.whathappy.cn"

-        indexRead arguments from command-line "http://www.lunjin.net"

-        indexRead arguments from command-line "http://www.ssstyle.cn"

-        indexRead arguments from command-line "http://www.91fish.cn"

-        indexRead arguments from command-line "http://www.fanselang.com"

Object initializeObject = object;

if (methodArray.length == 1) {

this.getHibernateTemplate().lock(initializeObject,

org.hibernate.LockMode.NONE);

initializeObject=PropertyUtils.getProperty(initializeObject,methodArray[0]);

this.getHibernateTemplate().initialize(initializeObject);

} else {

for (int j = 0; j < methodArray.length; j++) {

initializeObject=PropertyUtils.getProperty(initializeObject,methodArray[0]);

}

this.getHibernateTemplate().lock(initializeObject,

org.hibernate.LockMode.NONE);

this.getHibernateTemplate().initialize(initializeObject);

}

}

}

public void initialize(Collection collection, HashSet fInitializeFields)

throws SecurityException, NoSuchMethodException,

IllegalArgumentException, IllegalAccessException,

InvocationTargetException {

for (Iterator i = collection.iterator(); i.hasNext();) {

Object object = i.next();

this.initialize(object, fInitializeFields);

}

}

public void initialize(Object object) throws SecurityException,

NoSuchMethodException, IllegalArgumentException,

IllegalAccessException, InvocationTargetException {

this.getHibernateTemplate().lock(object, org.hibernate.LockMode.NONE);

this.getHibernateTemplate().initialize(object);

}

public void initialize(Collection collection, String methodName[])

throws SecurityException, NoSuchMethodException,

IllegalArgumentException, IllegalAccessException,

InvocationTargetException {

for (Iterator i = collection.iterator();i.hasNext(); ) {

Object object = i.next();

this.initialize(object, methodName);

}

}

Hibernate的强制加载策略

时间: 2024-10-07 13:22:30

Hibernate的强制加载策略的相关文章

hibernate集合的加载策略

在集合方配置lazy和fetch的方式,默认的是lazy为true,fetch为select,lazy有true和false,为true时注意session不要关闭,不然后续的集合属性获取就没法获取了,会报no session的错误,而fetch有select,join,subselect3种,其实也就是去数据库中获取数据时发送sql的形式不同,select为分开单独用查询对象和集合,而join为以对象为主的left join一起关联查询出来,此时lazy为true已经失效,适用于对象导航查询,

关于延迟加载(lazy)和强制加载(Hibernate.initialize(Object proxy) )

PO 即Persistence Object VO 即Value Object PO 和VO 是Hibernate 中两个比较关键的概念. 首先,何谓VO,很简单,VO 就是一个简单的值对象. 如: TUser user = new TUser(); user.setName("Emma"); 这里的user 就是一个VO.VO 只是简单携带了对象的一些属性信息. 何谓PO? 即纳入Hibernate 管理框架中的VO.看下面两个例子: TUser user = new TUser()

Rhythmk 学习 Hibernate 03 - Hibernate 之 延时加载 以及 ID 生成策略

Hibernate 加载数据 有get,跟Load 1.懒加载: 使用session.load(type,id)获取对象,并不读取数据库,只有在使用返回对象值才正真去查询数据库. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Test    public void  test1()    {        Session session = null;         try {             session = Hiber

hibernate的懒加载

一.lazy概述 在ORM中,当应用程序需要对关联关系的实体进行查询时,hibernate提供了一种查询加载方案--Lazy:延迟加载.当我们通过一个实体可以查询到引用的关联实体时,并不是马上就读取这个实体或者集合,而是在真正调用的时候才会发出查询语句,进行读取,这样可以提高系统的性能. lazy策略使用范围: <class>标签上:可以取值true/false. <property>标签上,属性延迟加载,可以取值true/false,这个特性需要类增强.对属性或返回单值的关联而言

hibernate中懒加载和及加载的区别

在hibernate中懒加载会去缓存中找,如果要找的是某一个对象不会出问题,如果是要找某一个对象包含的对象会报session关闭异常,应为我们在缓存中查找了对象过后session就关闭了,如果非要这样的话在实现类里面就可不能关闭session.然而及时加载就不会出现这些问题,及时加载时直接去数据库中查找出所有内容,不用担心会出现session异常关闭的问题.但是懒加载速度比及加载更快.

hibernate的懒加载问题

产生原因: 当使用hibernate查询一个对象的时候,如果Session关闭,再调用该对象关联的集合或者对象的时候,会产生懒加载异常! 解决方案: 方案一: 在Session关闭之前,查询对象关联的集合或者对象,所有在业务层的方法上添加: 1 public ElecUser findUserByLogonName(String name) { 2 3 String condition = " and o.logonName = ?"; 4 5 Object [] params = {

《Spring揭秘》(十) ---- ApplicationContext之统一资源加载策略

Spring的resource Spring框架内部使用Resource接口作为所有资源的抽象和接口.例如: BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("...")); ClassPathResource就是Resource的一个特定类型的实现,代表的实位于Classpath中的资源. Resource接口可以根据资源的不同类型,或者资源所处的不同场合,给出相应的具体实现: a. ByteArr

教你写Android ImageLoader框架之图片加载与加载策略

在教你写Android ImageLoader框架之初始配置与请求调度中,我们已经讲述了ImageLoader的请求配置与调度相关的设计与实现.今天我们就来深入了解图片的具体加载过程以及加载的策略(包括按顺序加载和逆序加载) ,在这其中我会分享我的一些设计决策,也欢迎大家给我提建议. 图片的加载 Loader与LoaderManager的实现 在上一篇文章教你写Android ImageLoader框架之初始配置与请求调度中,我们聊到了Loader与LoaderManager. ImageLoa

最新版本cocos2d&#173;2.0&#173;x&#173;2.0.2使用新资源加载策略!不再沿用-hd、-

 前段时间cocos2dx更新了最新版本cocos2d-2.0-x-2.0.2,也从这个版本开始对于资源加载与管理都改变了策略. 在之前的加载方式都是通过沿用与cocos2d-iphone一样的加载资源方式,对于图片名后添加-hd,-ipad,-ipadhd方式,当用户开启项目的高清视网膜后就可以默认寻找对应的资源.但是从cocos2d-2.0-x-2.0.2版本开始,资源加载策略不在如此了.对跨平台整合不清楚的请看cocos2dx最新2.x版本跨平台整合NDK+Xcode 最新资源加载策略