第二节: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. expdp/impdp 详细参数解释

    任意可以使用expdp/impdp的环境,都可以通过help=y看到帮助文档. 1.expdp参数说明 2.impdp参数说明 3.expdp参数说明(中文) 4.impdp参数说明(中文) expd ...

  2. springboot jpa 批量保存数据--EntityManager和 JpaRepository

    1: 项目里面使用springboo-boot-start-data-jpa操作数据库,通过源码,在repository上继承JpaRepository 可以实现保存操作,其中源码接口为: <S ...

  3. dilworth定理+属性排序(木棍加工)

    P1233 木棍加工 题目描述 一堆木头棍子共有n根,每根棍子的长度和宽度都是已知的.棍子可以被一台机器一个接一个地加工.机器处理一根棍子之前需要准备时间.准备时间是这样定义的: 第一根棍子的准备时间 ...

  4. 2018-2019-2 《网络对抗技术》Exp2 后门原理与应用 20165210

    2018-2019-2 <网络对抗技术>Exp2 后门原理与应用 20165210 实验内容: 使用netcat获取主机操作Shell,cron启动. 使用Socat获取主机操作Shell ...

  5. windows7 下安装python3.6开发环境

    所有的软件都放在百度云盘里: 链接: https://pan.baidu.com/s/1rux8sDK9thhbZ1qjwQg6kA 密码: iq4c 1. 安装python3.6.5 安装的时候要把 ...

  6. C++实现线程同步的几种方式

    线程同步是指同一进程中的多个线程互相协调工作从而达到一致性.之所以需要线程同步,是因为多个线程同时对一个数据对象进行修改操作时,可能会对数据造成破坏,下面是多个线程同时修改同一数据造成破坏的例子: # ...

  7. Java内存模型的深入理解

    基础 并发编程的模型分类 在并发编程需要处理的两个关键问题是:线程之间如何通信 和 线程之间如何同步. 通信 通信 是指线程之间以何种机制来交换信息.在命令式编程中,线程之间的通信机制有两种:共享内存 ...

  8. SAP NetWeaver Business Client (NWBC) 简介

    1.NWBC 简介 SAP NetWeaver Business Client (NWBC) 是新一代SAP用户界面,集成了SAPGUI事务和新的web dynpro应用,类似于桌面应用程序. SAP ...

  9. 音乐随想——德沃夏克《From The New World》

    第一乐章 前奏拖的很长,低音,再低音.突然转向,好像漂泊数月的水手看到了新大陆. 第二乐章 前奏很优美,到双簧管出现的时候宛若紫霞仙子撑船自芦苇荡中飘过. 之后又一段较前奏稍快的旋律,好像看到了梦寐的 ...

  10. Jenkins构建持续集成

    Jenkins 是一个开源软件项目,旨在提供一个开放易用的软件平台,使软件的持续集成变得可能.现在软件开发追求的是效率以及质量,Jenkins使得自动化成为可能! 亮点 采用shell自定义脚本,控制 ...