Hibernate4.x之Session--常用方法
接上篇文章继续学习Hibernate的Session(http://www.cnblogs.com/dreamfree/p/4111777.html)
持久化对象的状态;
站在持久化的角度,Hibernate把对象分为4种状态:持久化状态、临时状态、游离状态、删除状态。
Session的特定方法能使对象从一个状态转换到另一个状态。
临时对象(Transient):
在使用代理主键的情况下,OID通常为null
不处于Session的缓存中
在数据库中没有对应的记录
持久化对象(也叫“托管”)(Persist)
OID为null
位于Session缓存中
若在数据库中已经有和其对应的记录,持久化对象和数据库中的相关记录对应
Session在flush缓存时,会根据持久化对象的属性变化,来同步更新数据库
在同一个Session实例的缓存中,数据库表中的每条记录只对应唯一的持久化对象
删除对象(Removed):
在数据库中没有和其OID对应的记录
不再处于Session缓存中
一般情况下,应用程序不该再使用被删除的对象
游离对象(也叫"脱管")(Detached):
OID不为null
不再处于Session缓存中
一般情况下,游离对象是由持久化对象转变过来的,因此在数据库中可能还存在与它对应的记录
下面的图片说明了Hibernate中对象状态的转换:
Session的save方法
Session的save()方法使一个临时对象转变为持久化对象
Session的save()方法完成以下操作:
把News对象加入到Session缓存中,使它进入持久化状态
选用映射文件指定的标识符生成器,为持久化对象分配唯一的OID,在使用代理主键的情况下,setId()方法为News对象设置OID是无效的
计划执行一条insert语句:在flush缓存的时候
Hibernate通过持久化对象的OID来维持它和数据库相关记录的对应关系。当News对象处于持久化状态时,不允许程序随意修改它的ID
persist()和save()的区别:
当对一个OID不为null的对象执行save()方法时,会把该对象以一个新的OID保存到数据库中;但执行persist()方法时会抛出一个异常
Session的get()和load()方法
都可以根据给定的OID从数据库加载一个持久化对象
区别:
当数据库中不存在与OID对应的记录时,load()方法抛出ObjectNotFoundException异常,而get()方法返回null
两者采用不同的延迟检索策略:load()方法支持延迟加载策略。而get不支持
Session的update()方法
Session的update()方法使一个游离对象转变为持久化对象,并且计划执行一条update语句
若希望Session仅当修改了News对象的属性时,才执行update()语句,可以把映射文件中<class>元素的select-before-update设为true。该属性的默认值为false
当update()方法关联一个游离对象时,如果在Session的缓存中已经存在相同的OID的持久化对象,会抛出异常
当update()方法关联一个游离对象时,如果数据库中不存在相应的记录,也会抛出异常
Session的saveOrUpdate()方法
Session的saveOrUpdate()方法同时包含了save()与update()方法的功能
判定对象为临时对象的标准
Java对象的OID为null
映射文件中的<id>设置了unsaved-value属性,并且Java对象的OID取值与这个unsaved-value属性值匹配
Session的merge()方法
Session的delete()方法
Session的delete()方法既可以删除一个游离对象,也可以删除一个持久化对象
Session的delete()方法处理过程
计划执行一条delete语句
把对象从Session的缓存中删除,该对象进入删除状态
Hibernate的cfg.xml配置文件中有一个hibernate.use_identifier_rollback属性,其默认值为false,若把它设为true,将改变delete()方法的运行行为:delete()方法会把持久化对象或游离对象的OID设置为null,使它们变为临时对象
通过Hibernate调用存储过程
work接口:直接通过JDBC API来访问数据库的操作
Session的doWork(Work)方法用于执行Work对象指定的操作,即调用Work对象的execute()方法。Session会把当前使用的数据库连接传递给execute()方法
Hibernate与触发器协同工作
Hibernate与数据库中的触发器协同工作时,会造成两类问题
触发器使Session的缓存中的持久化对象与数据库中对应的数据不一致;触发器运行在数据库中,它执行的操作对Session是透明的
session的update()方法盲目地激发触发器;无论游离对象的属性是否发生变化,都会执行update语句,而update语句会激发数据库中相应的触发器
解决方案:
在执行完Session的相关操作后,立即调用Session的flush()方法和refresh()方法,迫使Session的缓存与数据库同步(refresh()方法重新从数据库加载对象)
在映射文件的<class>元素中设置select-before-update属性;当Session的update或saveOrUpdate()方法更新一个游离对象时,会先执行select语句,获得当前游离对象在数据库中的最新数据。只有在一致的情况下才会执行update语句
测试类:
package com.yl.hibernate.entities; import static org.junit.Assert.*; import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Date; import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.jdbc.Work;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test; public class HibernateTest { private SessionFactory sessionFactory;
private Session session;
private Transaction transaction; @Before
public void init() {
Configuration configuration = new Configuration().configure();
ServiceRegistry serviceRegistry =
new ServiceRegistryBuilder().applySettings(configuration.getProperties())
.buildServiceRegistry(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); session = sessionFactory.openSession(); transaction = session.beginTransaction();
}
@After
public void destory() {
transaction.commit(); session.close(); sessionFactory.close();
} @Test
public void testSessionCache() {
News news = (News)session.get(News.class, 21);
System.out.println(news);
session.flush();
News news2 = (News)session.get(News.class, 21);
System.out.println(news2); System.out.println(news == news2);//true
} /**
* flush:使数据库表中的记录和Session缓存中的对象的状态保持一致。为了保持一致,则可能会发送对应的SQL语句。
* 1.在Transaction的commit()方法中:先调用session的flush方法,再提交事务
* 2.flush()方法可能会发送SQL语句,但不会提交事务
* 3.注意:在为提交事务或显示调用session.flush()方法 之前,也有可能会flush()操作。
* 1).执行HQL或QBC查询,会先进行flush操作,以得到数据表的最新纪录
* 2).若记录的ID是由底层数据库使用自增的方式生成的,则在调用save方法时,就会立即发送INSERT语句
* 因为save方法后,必须保证对象的ID是存在的!
*/
@Test
public void testFlush2() {
News news = new News("Hibernate", "oracle", new Date());
session.save(news);
} @Test
public void testFlush() {
/*News news = (News)session.get(News.class, 21);
news.setAuthor("Bruce Eckel"); News news2 = (News)session.createCriteria(News.class).uniqueResult();
System.out.println(news2);*/
News news = (News)session.get(News.class, 22);
session.flush();
System.out.println(news);
} /**
* refresh():会强制发送SELECT 语句,以使Session缓存中对象的状态和数据表中对应的记录保持一致!
*/
@Test
public void testRefresh() {
News news = (News) session.get(News.class, 22);
System.out.println(news);
session.refresh(news);
System.out.println(news);
} /**
* clear():清理缓存
*/
@Test
public void testClear() {
News news1 = (News) session.get(News.class, 21);
session.clear();
News news2 = (News) session.get(News.class, 21);
} /**
* save()方法:
* 1.使一个临时对象变为持久化对象
* 2.为对象分配ID
* 3.在flush缓存时会发送一条insert语句
* 4.在save方法之前的id是无效的
* 5.持久化对象的ID是不能被修改的!
*/
@Test
public void testSave() {
News news = new News();
news.setTitle("AA");
news.setAuthor("aa");
news.setNewsDate(new Date());
//news.setId(100);//不起效果
System.out.println(news);
//news.setId(101);//抛出异常
session.save(news);
System.out.println(news);
}
/**
* persist():也会执行insert操作
* 和save()的区别:
* 在调用persist方法之前,若对象已经有ID了,则不会执行insert,而抛出异常
*/
@Test
public void testPsesist() {
News news = new News();
news.setTitle("DD");
news.setAuthor("dd");
news.setNewsDate(new Date());
//news.setId(200);//抛出异常
System.out.println(news);
session.save(news);
System.out.println(news);
} /**
*
*/
@Test
public void testGet() {
News news = (News) session.get(News.class, 21);
System.out.println(news);
} /**
* get 和 load
*
* 1.执行get方法,会立即加载对象。
* 而执行load方法,若不使用该对象,则不会立即执行查询操作,而返回一个代理对象
*
* get是立即检索,load是延迟检索
*
* 2.load方法可能会抛出LazyInitializationException(懒加载异常):在需要初始化代理对象之前已经关闭了session
*
* 3.若数据表中没有对应的记录,且session也没有被关闭。同时需要使用对象时
* get 返回null
* load 若不使用该对象的任何属性,则不会出问题;若要初始化了,抛出异常
*
*
*/
@Test
public void testLoad() {
News news = (News) session.load(News.class, 21);
System.out.println(news);
} /**
* update:
* 1.若更新一个持久化对象,不需要显式的调用update对象。因为在调用Transaction的commit方法时,会先执行session的flush方法。
* 2.更新一个游离对象,需要显式的调用session的update方法。可以把一个游离对象变为持久化对象
*
* 需要注意的:
* 1.无论要更新的游离对象和数据表中的记录是否一致,都会发送update语句。
* 如何能让update方法不再盲目的发送update语句,在.hbm.xml文件的class节点设置select-before-update的值为true,默认为flase。但通常不需要设置该属性
*
* 2.若数据表中没有对应的记录,但还调用了update方法,会抛出异常
*
* 3.当update()方法关联一个游离对象时,如果在Session的缓存中已经存在相同OID的持久化对象,会抛出异常。因为在Session缓存中不能有两个OID相同的对象
*/
@Test
public void testUpdate() {
/*News news = (News) session.get(News.class, 22);
news.setAuthor("Sun");//此时news的author字段已经更新到数据库中,因为在执行commit语句时会先执行flush,flush将session缓存中的修改同步到数据库中。
*/ News news = (News) session.get(News.class, 22);
transaction.commit();
session.close(); session = sessionFactory.openSession();
transaction = session.beginTransaction(); //news.setAuthor("Sun");
session.update(news); } /**
* 注意:
* 1.若OID不为空,但数据表还没有和其对应的记录。会抛出一个异常。
* 2.了解:OID值等于id的unsaved-value属性值的对象,也被认为是一个游离对象
*/
@Test
public void testSaveOrUpdate() {
News news = new News("FF", "ff", new Date());
news.setId(41);
session.saveOrUpdate(news); } /**
* delete: 执行删除操作,只要OID和数据表中一条记录对应,就会准备执行delete操作
* 若OID在数据表中没有对应的记录,则抛出异常
*
* 可以通过设置一个Hibernate配置文件hibernate.use_identifier_rollback 为true,使删除对象后,把其OID置为null
*/
@Test
public void testDelete() {
/*//游离对象删除
News news = new News();
news.setId(42); session.delete(news);*/ //持久化对象删除
News news = (News) session.get(News.class, 41);
session.delete(news);//计划删除,并不立即执行。在commit中的flush时执行delete
System.out.println(news);//依然可以打印
} /**
* evict:从session缓存中把指定的持久化对象移除
*/
@Test
public void testEvict() {
News news1 = (News) session.get(News.class, 22);
News news2 = (News) session.get(News.class, 41); news1.setTitle("AA");
news2.setTitle("BB"); session.evict(news1);
} /**
* 调用存储过程
*/
@Test
public void testDoWork() {
session.doWork(new Work() { @Override
public void execute(Connection connection) throws SQLException {
System.out.println(connection);
//调用存储过程 //创建存储过程的对象
CallableStatement c = connection.prepareCall("{call getsum(?,?)}"); //给存储过程的第一个参数设置值
c.setInt(1,100); //注册存储过程的第二个参数
c.registerOutParameter(2,java.sql.Types.INTEGER); //执行存储过程
c.execute(); connection.close();
}
});
}
}
Hibernate4.x之Session--常用方法的更多相关文章
- hibernate4中使用Session doWork()方法进行jdbc操作(代码)
Hibernate3.3.2版本中getSession().connection()已被弃用,hibernate4中官方推荐使用Session doWork()方法进行jdbc操作 首先看看Work接 ...
- 第二节 hibernate session介绍以及session常用方法介绍
原创地址:http://www.cnblogs.com/binyulan/p/5628579.html Session是java应用程序和hibernate框架之间的一个主要接口.它是从持久化服务中剥 ...
- Hibernate4.x之Session
Hibernate Session概述 Session接口是Hibernate向应用程序提供的操纵数据库的最主要的接口,它提供了基本的保存.更新.删除和加载Java对象的方法. Session具有一个 ...
- org.hibernate.Session常用方法的作用总结
clear(): 清理session缓存.把所有加载出来的持久化实例都从session缓存中清除,同时,也会挂掉当前session中正在排队的save,update,delete操作. evict: ...
- IT兄弟连 JavaWeb教程 Servlet会话跟踪 Session常用方法
● public Object getAttribute(String name) 该方法返回在该session会话中具有指定名称的对象,如果没有指定名称的对象,则返回null. ● public ...
- Django session/cookie
一.cookie 常用方法: 获取: 需要在消息体设置值 1:设置cookie def login(request): if request.method == "POST": ...
- Session实例
Session常用方法(一) session对象用来保存一些在与每个用户回话期间需要保存的数据信息,这样就方便了回话期间的一些处理程序.如可以用session变量记住用户的用户名,以后就不必在其他的网 ...
- JavaWeb -cookie&session&application
cookie&session&application总结 Cookie[key-value](不是内置对象必须new): 1. Cookie 是由服务端生成的,在发送给客户端保存 2. ...
- Hibernate4 拦截器(Interceptor) 实现实体类增删改的日志记录
转自:https://blog.csdn.net/he90227/article/details/44783099 开发应用程序的过程中,经常会对一些比较重要的数据修改都需要写日志.在实际工作的工程中 ...
- JSP + Session Cookie详解
篇幅较大,对JSP进行了非常详细的讲解,并解释了Session和Cookie的实现原理 ,预计看完需要20分钟左右,慢慢享受吧 JSP概述 掌握了servlet后,就可以利用servlet来开发动态页 ...
随机推荐
- jdbc mysql 取数,突然取不到数据,数据库中有数据
项目用的是jdbc+mysql,局网取数据的时候,数据一切正常,但是传到服务器上以后,曾经是好的 不知道为什么,近期一传就取不到数据,发现android写的也没有问题,至少大体上没有语法问题. 跟踪后 ...
- iOS通过http post上传图片 (转)
转载自:http://www.cocoachina.com/bbs/read.php?tid=89985 由于iOS无法通过html表单来上传图片,因此想要上传图片,必须实现http请求,而不能像其他 ...
- iOS中的固定 高度
iOS键盘高度 英文 216(不带联想功能) 英文 252(带联想功能) 中文 252 系统自带表情键盘的高度是 253 在使用系统键盘的时候,如果遇到输入框被键盘挡住的情况 就要用通知中心 ...
- Oralce11 客户端的安装和 PlSql Developer 的配置
关于Oracle11服务器端安装时的配置问题我就不讲了,就是要安装DataBase1和DataBase2. 现在我来讲的是Oralce11 客户端的安装和PlSql的配置问题: 步骤一:选择图示,wi ...
- ExtJs gridPanel Column 时间格式化
var panel = new Ext.container.Viewport({ items: { xtype: 'gridpanel', id: 'gridPanel', store: store, ...
- Samba出现“您可能没有权限使用网络资源”解决方法
我最近在Centos6.3上搭建Samba系统,按照配置都已经配置好了,当就是没法在win7下访问,老是弹出以下弹出框: 后来我在网上找资料发现有SELinux这么个东西,然后我就按照配置该了一下就成 ...
- MyEclipse中文注释乱码解决
MyEclipse中文注释乱码解决 将别人的项目或JAVA文件导入到自己的Eclipse中时,常常会出现JAVA文件的中文注释变成乱码的情况,主要原因就是别人的IDE编码格式和自己的Eclipse编码 ...
- 【数学/扩展欧几里得/Lucas定理】BZOJ 1951 :[Sdoi 2010]古代猪文
Description “在那山的那边海的那边有一群小肥猪.他们活泼又聪明,他们调皮又灵敏.他们自由自在生活在那绿色的大草坪,他们善良勇敢相互都关心……” ——选自猪王国民歌 很久很久以前,在山的那边 ...
- IOS xib生成界面和代码生成界面两种方式混合
应用程序代理类 WKAppDelegate.m // // WKAppDelegate.m // HelloWorld // // Created by easy5 on 13-9-18. // Co ...
- eclipse 安装配置maven
1.安装maven 插件 从eclipse 3.7(indigo)之后,m2e 插件已host到eclipse.org 站点下: Since Eclipse 3.7 (Indigo), m2e is ...