小女巫 发表于 2015-1-18 10:59:54

来看Hibernate进修(二)Hibernate中Session之get和load办法的真正区分

最后我再次声明,我并没有说不看好java,实际上我对java很乐观的,毕竟她正在不断改进中,我相信她总有一天会和.net并驾齐驱的
比来在进修SHH框架中的Hibernate,对Session的get和load办法,有点混不分明,不晓得区分在哪,大概对它们的区分感到不深。以是百度了一下,了局成绩来了。百度的了局和实践测试的了局收支很年夜。次要是对get办法的说法跟实践运转的了局纷歧致。
先说一下概念吧:
get不撑持lazy,load撑持lazy;
数据不存在时,get前往null,load则抛出ObjectNotFoundException非常。
load办法能够前往实体的代办署理类实例,而get办法间接读取数据库,以是间接前往实体类(get的这个说法是毛病的)
关于第一条,信任人人都没有太多的疑问。我这里给个例子稍作注释:lazy意味着用的时分才往实行sql语句。
Useruser=(User)session.load(User.class,"4028981b41174a690141174a6c6d0003");
这句代码不会往实行数据库查询,只要用到user时才会往实行数据库查询。以是不会当即天生sql语句。
Useruser=(User)session.get(User.class,"4028981b41174a690141174a6c6d0003");而下面这句代码则会当即往实行数据库查询(假如缓存中没有实例)。
尔后面的成绩要想申明白,起首得懂得一个成绩——Session加载实体对象的历程:
起首,Hibernate中保持了两级缓存。第一级缓存由Session实例保护,它是属于事件局限的缓存。个中坚持了Session以后一切联系关系实体的数据,也称为外部缓存。而第二级缓存则存在于SessionFactory条理,它是属于历程局限或聚集局限的缓存,由以后一切由本SessionFactory机关的Session实例共享。
出于功能思索,制止无谓的数据库会见,Session在挪用数据库查询功效之前,会先在缓存中举行查询。起首在第一级缓存(外部缓存)中,经由过程实体范例和id举行查找,假如第一级缓存查找射中,且数据形态正当,则间接前往。然后,Session会在以后“NonExists”纪录中举行查找,假如“NonExists”纪录中存在一样的查询前提,则前往null。“NonExists”纪录了以后Session实例在之前一切查询操纵中,未能查询到无效数据的查询前提(相称于一个查询黑名单列表)。云云一来,假如Session中一个有效的查询前提反复呈现,便可敏捷作出判别,从而取得最好的功能体现。
关于load办法而言,起首查找外部缓存,假如射中,则前往实例,假如外部缓存中未发明无效数据,则查询第二级缓存,假如第二级缓存射中,则前往。若二级缓存中仍旧未发明无效数据,则倡议数据库查询操纵(SelectSQL)。假如查询到,则前往实体类的代办署理对象,若经由查询未发明对应纪录,则将此次查询的信息在“NonExists”中加以纪录,并抛出ObjectNotFoundException非常。
关于get办法而言,很多书上、收集博客里都说错了。get办法一样是先查找外部缓存,假如射中,则前往,不然倡议数据库查询操纵,假如查询到,则前往实体类的对象,若经由查询未发明对应纪录,则将此次查询的信息在“NonExists”中加以纪录,并前往null。以是收集上说的“当别人修正了数据后,用load大概读取不到最新的数据,而get一定能够读取到最新修正的数据”的说法也是不建立的。
这也就意味着,get办法猎取到的其实不必定是实体类对象,load办法也纷歧定是前往实体代办署理类对象。
以上的概念都是我经由过程测试得出来的,有代码有图有原形呀:

packagecom.bjpowernode.hibernate;

importjava.util.Date;

importjunit.framework.TestCase;

importorg.hibernate.ObjectNotFoundException;
importorg.hibernate.Session;
importorg.hibernate.Transaction;

/**
*Session测试类
*
*@authorLongxuan
*
*/
publicclassSessionTestextendsTestCase{

publicvoidtestEquals(){
Sessionsession=null;
try{

//猎取Session
session=HibernateUtils.getSession();
//开启事件
session.beginTransaction();
System.out.println("



");
try{

//考证查不到数据时,get前往null,load抛ObjectNotFoundException非常
                        //URL:http://www.bianceng.cn/Programming/Java/201410/45828.htm
System.out.println(session.get(User.class,"123"));
System.out.println(session.load(User.class,"123"));

}catch(ObjectNotFoundExceptione){

System.out.println("load办法抛出ObjectNotFoundException非常");

}

System.out.println("

");



//考证load前往实体类对象,而非代办署理对象
{
Useruser1=(User)session.get(User.class,"4028981b41174a690141174a6c6d0003");
Useruser2=(User)session.load(User.class,"4028981b41174a690141174a6c6d0003");
System.out.println("user1:"+user1.getClass().getSimpleName());
System.out.println("user2:"+user2.getClass().getSimpleName());
System.out.println("user1与user2是不是为统一对象:"+user1.equals(user2));
}

System.out.println("

");
session.clear();//扫除Session


//考证get也能够前往代办署理类对象,而其实不必定前往实体类对象
//同时考证了get办法先查找缓存(假如没有输入sql语句,则申明get查找了缓存)
{
Useruser3=(User)session.load(User.class,"4028981b41174a690141174a6c6d0003");
Useruser4=(User)session.get(User.class,"4028981b41174a690141174a6c6d0003");
System.out.println("user3:"+user3.getClass().getSimpleName());
System.out.println("user4:"+user4.getClass().getSimpleName());
System.out.println("user3与user4是不是为统一对象:"+user3.equals(user4));
}


session.getTransaction().commit();

}catch(Exceptione){

e.printStackTrace();
session.getTransaction().rollback();

}finally{
HibernateUtils.closeSession(session);
}

}
}运转了局图:

另有一个风趣的征象:

Useruser5=(User)session.load(User.class,"123");
System.out.println(user5.getId());运转了局间接输入123
从了局中也能够看出,前2句代码,不会往实行数据库操纵。由于load后会在hibernate的一级缓存里寄存一个map对象,该map的key就是Id的值,可是当你getId()时,它会往一级缓存里拿map的key值,恰好找到了,以是不会再往实行数据库查询。也不会报任何错。就有了以上的了局。

微软什么都提供了。你可以试想一下,如果你是新手,你是希望你点一下按钮程序就能运行那,还是想自己一点一点的组织结构,然后打包发部,调错再打包......

简单生活 发表于 2015-1-19 21:48:24

自从Sun推出Java以来,就力图使之无所不包,所以Java发展到现在,按应用来分主要分为三大块:J2SE,J2ME和J2EE,这也就是Sun ONE(Open Net Environment)体系。J2SE就是Java2的标准版,主要用于桌面应用软件的编程;J2ME主要应用于嵌入是系统开发,如手机和PDA的编程;J2EE是Java2的企业版,主要用于分布式的网络程序的开发,如电子商务网站和ERP系统。

admin 发表于 2015-1-22 08:30:14

是一种使用者不需花费很多时间学习的语言

蒙在股里 发表于 2015-1-27 05:44:00

Java 不同于一般的编译执行计算机语言和解释执行计算机语言。它首先将源代码编译成二进制字节码(bytecode),然后依赖各种不同平台上的虚拟机来解释执行字节码。从而实现了“一次编译、到处执行”的跨平台特性。

小女巫 发表于 2015-2-4 23:01:17

你快去找一份Java的编程工作来做吧(如果是在校学生可以去做兼职啊),在实践中提高自己,那才是最快的。不过你得祈祷在公司里碰到一个高手,而且他 还愿意不厌其烦地教你,这样好象有点难哦!还有一个办法就是读开放源码的程序了。我们知道开放源码大都出自高手,他们设计合理,考虑周到,再加上有广大的程序员参与,代码的价值自然是字字珠叽,铿锵有力(对不起,偶最近《金装四大才子》看多了)。

再现理想 发表于 2015-2-10 22:33:58

你快去找一份Java的编程工作来做吧(如果是在校学生可以去做兼职啊),在实践中提高自己,那才是最快的。不过你得祈祷在公司里碰到一个高手,而且他 还愿意不厌其烦地教你,这样好象有点难哦!还有一个办法就是读开放源码的程序了。我们知道开放源码大都出自高手,他们设计合理,考虑周到,再加上有广大的程序员参与,代码的价值自然是字字珠叽,铿锵有力(对不起,偶最近《金装四大才子》看多了)。

乐观 发表于 2015-3-1 16:51:16

吧,现在很流行的Structs就是它的一种实现方式,不过Structs用起来实在是很繁,我们只要学习其精髓即可,我们完全可以设计自己的MVC结构。然后你再研究一下软件Refactoring (重构)和极限XP编程,相信你又会上一个台阶。 做完这些,你不如整理一下你的Java代码,把那些经典的程序和常见的应用整理出来,再精心打造一番,提高其重用性和可扩展性。你再找几个志同道合的朋友成立一个工作室吧

海妖 发表于 2015-3-10 20:03:21

不过,每次的执行编译后的字节码需要消耗一定的时间,这同时也在一定程度上降低了 Java 程序的运行效率。

飘飘悠悠 发表于 2015-3-17 09:34:22

是一种由美国SUN计算机公司(Sun Microsystems, Inc.)所研究而成的语言

愤怒的大鸟 发表于 2015-3-24 06:08:19

让你能够真正掌握接口或抽象类的应用,从而在原来的Java语言基础上跃进一步,更重要的是,设计模式反复向你强调一个宗旨:要让你的程序尽可能的可重用。
页: [1]
查看完整版本: 来看Hibernate进修(二)Hibernate中Session之get和load办法的真正区分