|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
最后我再次声明,我并没有说不看好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值,恰好找到了,以是不会再往实行数据库查询。也不会报任何错。就有了以上的了局。
微软什么都提供了。你可以试想一下,如果你是新手,你是希望你点一下按钮程序就能运行那,还是想自己一点一点的组织结构,然后打包发部,调错再打包...... |
|