第二节:Session 常用方法讲解                                        
2)load和get()方法:
数据库中不存在与OID 对应的记录,Load()方法会抛出异常:
load方法默认采用延迟加载,load出来的对象是一个代理类。开始并没有值,只有用到它的属性等的时候,才会去发出sql语句。
而get方法一开始就发出sql语句。
 
如果说获取一个对象是为了删除它,可以用load,因为只要获取个引用就行了。
如果说获取一个对象是为了访问它的属性,建议用get;
@Test
public void testLoadClass() {
Class c = (Class) session.load(Class.class, Long.valueOf(2)); //class id为2的不存在,抛出异常
System.out.println(c.getStudents());
} @Test
public void testGetClass() {
Class c = (Class) session.get(Class.class, Long.valueOf(2)); //class id为2的不存在,打印null
System.out.println(c);
}

2)update:

@Test
public void testUpdateClass(){
Session session1=sessionFactory.openSession();
session1.beginTransaction();
Class c=(Class)session1.get(Class.class, Long.valueOf(1));
session1.getTransaction().commit();
session1.close(); Session session2=sessionFactory.openSession();
session2.beginTransaction();
c.setName("08计算机本科2");
session2.update(c);
session2.getTransaction().commit();
session2.close();
}

补充:

update方法:
1.更新一个detached的对象;
2.更新一个transient的会报错;但是更新自己设定id的transient对象可以(数据库有对应记录);
3.上面的,比如更新teacher,我们只是想更新name,但是它会把所有的属性都更新一遍;这样会造成效率低,比如有个字段特别长...
4.持久化的对象,只要改变了它的内容,session在提交或者关闭的时候,会检查缓存中的和数据库中的是否一致,如果不一致,自动的发update语句;
但是也和上面一样,虽然只改了一个字段,也会更新所有的字段;
5.能不能做到:哪个字段改了才更新,哪个字段没改,哪个字段就不更新?怎么做:
a.xml配置:
<class name="com.cy.Teacher" dynamic-update="true">.....</class>
b.跨session更新的问题:
@Test
public void testUpdate5() { Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Student s = (Student)session.get(Student.class, 1);
s.setName("zhangsan5");
session.getTransaction().commit(); s.setName("z4"); Session session2 = sessionFactory.getCurrentSession();
session2.beginTransaction();
session2.update(s);
session2.getTransaction().commit();
}
首先student对象被我们放到了缓存里,s.setName("zhangsan3"),Hibernate会检查哪些属性改过了,这时候生成sql语句,由于使用了dynamic-update,它就只更新name这个字段了;
session提交之后,关闭了。缓存中的这个对象没了。但是内存中Student s这个对象还在,是detached状态的。
这个对象又setName("z4"),第二个session2来了,这个session2里面没有s这个对象,然后update(s),它有没有地方来比较哪个字段改过了?
没有,它没法将内存中的s和session2缓存中的s来比较,所以update(s),发出的sql会更新全部的字段; c.根据上面,如果想跨session,只更新改过的字段,怎么做:
将上面的update改为merge:
@Test
public void testUpdate6() { Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Student s = (Student)session.get(Student.class, 1);
s.setName("zhangsan6");
session.getTransaction().commit(); s.setName("z4"); Session session2 = sessionFactory.getCurrentSession();
session2.beginTransaction();
session2.merge(s);
session2.getTransaction().commit();
}
merge:把这个对象给我合并到数据库;原来没改的内容还需要合并吗?不需要。
merge的时候,它怎么检查哪些字段改过哪些字段没改过呢?缓存中又没有,只能从数据库中load一次,所以它在update之前先发出了一条select语句,然后再比较你给我的对象和我load的对象在什么地方不同,再重新发update语句。 d:dynamic-update这种xml配置,对应的JPA Annotation没有对应的属性;
在真正开发中建议使用HQL:
session.createQuery("update Student s set s.name='z5' where s.id = 1");
@Test
public void testUpdate7() {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Query q = session.createQuery("update Student s set s.name='z5' where s.id = 1");
q.executeUpdate();
session.getTransaction().commit(); }

3)saveOrUpdate:

saveOrUpdate(): 如果传的是一个临时对象,则执行save方法;如果传的是游离对象,就调用update方法;
@Test
public void testSaveOrUpdateClass(){
Session session1=sessionFactory.openSession();
session1.beginTransaction();
Class c=(Class)session1.get(Class.class, Long.valueOf(1));
session1.getTransaction().commit();
session1.close(); Session session2=sessionFactory.openSession();
session2.beginTransaction();
c.setName("08计算机本科3"); Class c2=new Class();
c2.setName("09计算机本科3");
session2.saveOrUpdate(c); //c是游离状态,执行update
session2.saveOrUpdate(c2); //c2临时状态,执行save
session2.getTransaction().commit();
session2.close(); /**
* 发出的sql:
* Hibernate: select class0_.classId as classId1_0_0_, class0_.className as classNam2_0_0_ from t_class class0_ where class0_.classId=?
Hibernate: insert into t_class (className) values (?)
Hibernate: update t_class set className=? where classId=?
*/
}

4)merge:

有的时候update会报错:session中有两个对象,拥有相同的OID(比如OID为1),更新的时候,session发现缓存中你已经有一个OID为1的对象了,所以更新的时候就报错了;
比如:
@Test
public void testUpdateClass2(){
Session session1=sessionFactory.openSession();
session1.beginTransaction();
Class c=(Class)session1.get(Class.class, Long.valueOf(1));
session1.getTransaction().commit();
session1.close(); Session session2=sessionFactory.openSession();
session2.beginTransaction();
Class c2=(Class)session2.get(Class.class, Long.valueOf(1));
c.setName("08计算机本科3"); session2.update(c);
session2.getTransaction().commit();
session2.close();
}

执行报错:

为了解决这个问题,多了个merge方法,合并对象:
更新的时候如果发现这个对象OID和session缓存中另一个对象OID重合了,调用merge方法就会合并,把这两个对象的属性合并,然后更新;
@Test
public void testMergeClass(){
Session session1=sessionFactory.openSession();
session1.beginTransaction();
Class c=(Class)session1.get(Class.class, Long.valueOf(1));
session1.getTransaction().commit();
session1.close(); Session session2=sessionFactory.openSession();
session2.beginTransaction(); Class c2=(Class)session2.get(Class.class, Long.valueOf(1));
c.setName("08计算机本科4"); session2.merge(c); session2.getTransaction().commit();
session2.close();
}

5)delete:

@Test
public void testDeleteStudent(){
Student student=(Student)session.load(Student.class, Long.valueOf(1));
session.delete(student);
session.getTransaction().commit();
session.close();
}

因为删除的时候,只需要获得它的引用,这里使用了load延迟加载就行了。不需要使用get了,因为不需要获取它里面的属性。

session.delete的时候还没有真正删除,提交事务的时候,才同步数据库,真的删了。

 
 

Hibernate学习5—Hibernate操作对象2的更多相关文章

  1. Hibernate学习之——Hibernate环境搭建

    之前在写关于安卓闹钟的教程,写了一半就没后一半了,其实自己也没做好,在校外实习,校内毕业实习又有任务,只能先放放了,等毕业实习结束之后,在继续安卓闹钟开发之旅,相信这个时间不会很久的.现在毕业实习用到 ...

  2. Hibernate学习笔记-Hibernate HQL查询

    Session是持久层操作的基础,相当于JDBC中的Connection,通过Session会话来保存.更新.查找数据.session是Hibernate运作的中心,对象的生命周期.事务的管理.数据库 ...

  3. Hibernate学习0.Hibernate入门

    Hibernate是什么 面向java环境的对象/关系数据库映射工具. 1.开源的持久层框架. 2.ORM(Object/Relational Mapping)映射工具,建立面向对象的域模型和关系数据 ...

  4. hibernate学习之Hibernate API

    1. Hibernate Api分类 1)提供访问数据库的操作(如保存,更新,删除,查询)的接口.这些接口包括:Session, Transaction,,Query接口. 2)由于配置Hiberna ...

  5. Hibernate学习之Hibernate流程

    Hibernate的核心组件 在基于MVC设计模式的JAVA WEB应用中,Hibernate可以作为模型层/数据访问层.它通过配置文件(hibernate.properties或hibernate. ...

  6. Hibernate学习二----------hibernate简介

    © 版权声明:本文为博主原创文章,转载请注明出处 1.hibernate.cfg.xml常用配置 - hibernate.show_sql:是否把Hibernate运行时的SQL语句输出到控制台,编码 ...

  7. hibernate学习 六 Hibernate缓存

    缓存: 如果在集群环境下使用Hibernate时,(集群有节点A ,节点B) 当请求,发往A节点,A在数据库中修改了一条记录,然后节点B的缓存中如何实时的更新节点A修改的新数据          hi ...

  8. Hibernate学习5—Hibernate操作对象

    第一节:Hibernate 中四种对象状态 删除状态:处于删除状态的Java 对象被称为删除对象.比如说session delete一个对象,这个对象就不处于session缓存中了, 已经从sessi ...

  9. Hibernate学习笔记三:对象关系映射(一对一,一对多,多对一,多对多)

    如需转载,请说明出处:http://www.cnblogs.com/gudu1/p/6895610.html Hibernate通过关系映射来表示数据库中表与表之间的关系,关系映射可以通过两种方式:配 ...

随机推荐

  1. 十八、dbms_repair(用于检测,修复在表和索引上的损坏数据块)

    1.概述 作用:用于检测,修复在表和索引上的损坏数据块. 2.包的组成 1).admin_tables语法:dbms_repair.admin_tables(table_name in varchar ...

  2. 转载-lvs官方文档04-LVS集群的负载调度

    LVS集群的负载调度 章文嵩 (wensong@linux-vs.org) 2002 年 5 月 本文主要讲述了LVS集群的IP负载均衡软件IPVS在内核中实现的各种连接调度算法.针对请求的服务时间变 ...

  3. HP数组转JSON函数json_encode和JSON转数组json_decode函数的使用方法

    这两个函数比较简单,我这里直接写例子,但是有一点一定要注意,json数据只支持utf-8格式,GBK格式的数据转换为json会报错! json_encode()用法: <?php$data =a ...

  4. iOS 数组集合操作(交集,并集,差集,子集)

    1.求数组的 交集,并集,差集 NSArray *array1 = @[@"1",@"2",@"3"]; NSArray *array2 = ...

  5. L150 Mystery Illness Causing Paralysis in Children Baffles Doctors

    Federal and state health officials are baffled by a mysterious and rare illness that seems to target ...

  6. Vim技能修炼教程(12) - Vim的脚本语言支持

    Vim的脚本语言支持 本节开始,我们正式接触vimscript这门古老的脚本语言. 首先要说明,vim支持的扩展语言很多,比如python, python3, ruby, lua,tcl等常见脚本语言 ...

  7. couldn't import dot_parser

    这个错误,你不要信它,实际可以画图了.害我又降级安装,真是气死了.

  8. 用python验证蒙提霍尔问题

    最初看到这个问题是初中的时候买了一本有关数学谜题的书里面概率论的一张的课后拓展就是说到三门问题,当时作为一个扩展阅读看了一下,里面说到了一个世界智商最高的女人秒杀了美国一大群的数学高材生的精彩故事(比 ...

  9. 【test】

    {"type":[    {"name":"专题分类","num":1,"value":[      ...

  10. 关于掌握C#的内存堆栈概念

    很多时候,我们使用C#语言书写业务逻辑时,并不会太多地主动考虑到内存的占用和分配问题,但编的程序多了,就总会遇到一些性能问题.提到"性能"二字,就不得不考虑CPU和内存,而提到内存 ...