关于延迟加载(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(); 

TUser anotherUser = new TUser(); 

user.setName("Emma"); 

anotherUser.setName("Kevin"); 


//此刻user和anotherUser都是VO 


Transaction tx = session.beginTransaction(); 

session.save(user);


//此刻的user现已经过Hibernate的处置,成为一个PO ,而anotherUser依然是个VO 


tx.commit(); 


//业务提交以后,库表中现已刺进一条用户”Emma”的记载,关于anotherUser则无任何操作


Transaction tx = session.beginTransaction(); 

user.setName("Emma_1"); //PO 

anotherUser.setName("Kevin_1");//VO 

tx.commit(); 


//业务提交以后,PO的状况被固化到数据库中,也即是说数据库中“Emma”的用户记载现已被更新为“Emma_1”,此刻anotherUser依然是个通常Java方针,它的特点更改不会对数据库产生任何影响,别的,经过Hibernate回来的方针也是PO: 由Hibernate回来的PO ,如:


TUser user = (TUser)session.load(TUser.class,new Integer(1)); 


VO经过Hibernate进行处置,就成为了PO。上面的示例代码session.save(user)中,咱们把一个VO “user”传递给Hibernate的Session.save办法进行保留。在save办法中,Hibernate对其进 

行如下处置: 

1. 在当时session所对应的实体容器(Entity Map)中查询是不是存在user方针的引证。 

2. 假如引证存在,则直接回来user方针id,save进程完毕. Hibernate中,关于每个Session有一个实体容器(实践上是一个Map方针), 假如此容器中现已保留了方针方针的引证,那么hibernate 会以为此方针现已与Session相有关。 

关于save操作而言,假如方针现已与Session相有关(即现已被参加Session 的实体容器中),则无需进行详细的操作。由于以后的Session.flush 进程中,Hibernate会对此实体容器中的方针进行遍历,查找出发作改变的实体,生成并履行相应的update句子。 

3. 假如引证不存在,则依据映射联系,履行insert操作。 

a) 在咱们这儿的示例中,采用了native的id生成机制,因而hibernate会从数据库取得insert操作生成的id并赋予user方针的id特点。 

b) 将user方针的引证归入Hibernate的实体容器。 

c) save 进程完毕,回来方针id. 

而Session.load办法中,再回来方针之前,Hibernate 就现已将此方针归入其实体容器中。


VO和PO的首要差异在于: 


. VO是独立的Java Object。 

. PO是由Hibernate归入其实体容器(EntityMap)的方针,它代表了与数 

据库中某条记载对应的Hibernate实体,PO的改变在业务提交时将反应到实 

际数据库中。假如一个PO与Session对应的实体容器中别离(如Session 封闭后的PO),那么 

此刻,它又会成为一个VO。


关于unsaved-value 


在非显现数据保留时,Hibernate 将依据这个值来判别方针是不是需求保留。 

所谓显式保留,是指代码中清晰调用session 的save 、update 、saveOrupdate 办法对方针进行持久化。如:


session.save(user); 


而在某些情况下,如映射联系中,Hibernate 依据级联(Cascade )联系对联接类进行保留。此刻代码中没有关于级联方针的显现保留句子,需求Hibernate 依据方针当时状 

态判别是不是需求保留到数据库。此刻,Hibernate 行将依据unsaved-value 进行断定。 

首要Hibernate 会取出方针方针的id。以后,将此值与unsaved-value 进行比对,假如相等,则以为方针方针没有保留,不然,以为方针现已保留,无需再进行保留操作。 

如:user 方针是之前由hibernate 从数据库中获取,一起,此user 方针的若干个有关方针address 也被加载,此刻咱们向user 方针新增一个address 方针,此刻调用 

session.save(user),hibernate 会依据unsaved-value 判别user 方针的数个address 

有关方针中,哪些需求履行save 操作,而哪些不需求。


关于咱们新参加的address 方针而言,由于其id(Integer 型)没有赋值,因而为null,与咱们设定的unsaved-value(null )相同,因而hibernate 将其视为一个未保留方针,将为其生成insert 句子并履行。


这儿能够会产生一个疑问,假如“原有”有关方针发作改变(如user 的某个“原有” 的address 方针的特点发作了改变,所谓“原有”即此address 方针现已与user 相有关,而不是咱们在此进程中为之新增的),此刻id 值是从数据库中读出,并没有发作改变,天然 

与unsaved-value(null)也不一样,那么Hibernate 是不是就不保留了? 


上面关于PO、VO 的评论中从前涉及到数据保留的疑问,实践上,这儿的“保留”, 实践上是“insert”的概念,仅仅关于新有关方针的参加,而非数据库华夏有有关方针的 

“update”。所谓新有关方针,通常情况下能够理解为未与Session 发作有关的VO。而“原有”有关方针,则是PO。: 


关于save操作而言,假如方针现已与Session相有关(即现已被参加Session的实体容器中),则无需进行详细的操作。由于以后的Session.flush 进程中,Hibernate 

会对此实体容器中的方针进行遍历,查找出发作改变的实体,生成并履行相应的update 句子。


Inverse和Cascade 


Inverse,直译为“回转”。在Hibernate语义中,Inverse 指定了相相联系中的方向。相相联系中,inverse=”false”的为主动方,由主动方担任保护相相联系。详细可参见一对多联系中的描绘。


而Cascade,译为“级联”,标明方针的级联联系,如TUser 的Cascade设为all, 就标明假如发作对user方针的操作,需求对user所有关的方针也进行相同的操作。如对user方针履行save操作,则有必要对user方针相有关的address也履行save操作。


初学者常常混杂inverse和cascade,实践上,这是两个互不有关的概念。Inverse 指的是相相联系的操控方向,而cascade指的是层级之间的连锁操作。


推迟加载(Lazy Loading) 


为了防止一些情况下,相相联系所带来的无谓的功用开支。Hibernate引入了推迟加载的概念。如,示例中user方针在加载的时分,会一起读取其所有关的多个地址(address)方针, 

关于需求对address进行操作的应用逻辑而言,有关数据的主动加载机制确实非常有用。可是,假如咱们仅仅想要取得user的性别(sex)特点,而不关心user的地址(address) 

信息,那么主动加载address的特性就显得剩余,而且造成了极大的功用浪费。为了取得user 的性别特点,咱们能够还要一起从数据库中读取数条无用的地址数据,这致使了很多无谓的体系开支。


推迟加载特性的呈现,恰是为了处理这个疑问。所谓推迟加载,即是在需求数据的时分,才真实履行数据加载操作。


关于咱们这儿的user方针的加载进程,也就意味着,加载user方针时只关于其自身的特点, 而当咱们需求获取user方针所有关的address信息时(如履行user.getAddresses时),才 

真实从数据库中加载address数据并回来。 

测验履行以下代码:


Criteria criteria = session.createCriteria(TUser.class); 


criteria.add(Expression.eq("name","Erica")); 

List userList = criteria.list(); 

-        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"

TUser user =(TUser)userList.get(0); 


System.out.println("User name => "+user.getName()); 

Set hset = user.getAddresses(); 


session.close();//封闭Session


TAddress addr = (TAddress)hset.toArray()[0]; 

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


运行时抛出反常: 

LazyInitializationException - Failed to lazily initialize a collection - no session or session was closed 


假如咱们稍做调整,将session.close放在代码结尾,则不会发作这样的疑问。这意味着,只要咱们实践加载user 有关的address时,Hibernate 才企图经过 

session从数据库中加载实践的数据集,而由于咱们读取address之前现已封闭了session,所以报出session已封闭的过错。


这儿有个疑问,假如咱们采用了推迟加载机制,但期望在一些情况下,完成非推迟加载时的功用,也即是说,咱们期望在Session封闭后,依然答应操作user的addresses 

特点。如,为了向View层供给数据,咱们有必要供给一个完好的User方针,包含其所有关的address信息,而这个User方针有必要在Session封闭以后依然能够运用。


Hibernate.initialize办法能够经过强行加载有关方针完成这一功用: 


Hibernate.initialize(user.getAddresses()); 

session.close(); 

//经过Hibernate.initialize办法强行读取数据 

//addresses方针即可脱离session进行操作


Set hset= user.getAddresses(); 

TAddress addr = (TAddress)hset.toArray()[0]; 

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


为了完成透明化的推迟加载机制,hibernate进行了很多努力。其中包含JDK Collection接口的独立完成。 

假如咱们测验用HashSet强行转化Hibernate回来的Set 型方针: 


Set hset = (HashSet)user.getAddresses(); 


就会在运行期得到一个java.lang.ClassCastException, 实践上,此刻回来的是一个Hibernate的特定Set完成“net.sf.hibernate.collection.Set”方针,而非 

传统意义上的JDK Set完成。这也恰是咱们为何在编写POJO时,有必要用JDKCollection 接口(如Set,Map), 而非特定的JDKCollection 完成类(如HashSet、HashMap)申明Collection特点的缘由。


关于延迟加载(lazy)和强制加载(Hibernate.initialize(Object proxy) ),古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。