原创地址:http://www.cnblogs.com/binyulan/p/5628579.html  

  Session是java应用程序和hibernate框架之间的一个主要接口。它是从持久化服务中剥离出来的一个非常重要的API接口。

  Session的主要功能是为映射的实体类的实例提供增删改查操作(User.class 为被映射的实体类,new User()即为实例)。这些实例可能是以下三种状态之一:

  1) transient: 从没有被持久化,不在Session缓存中
  2) persistent: 在Session的缓存中。
  3) detached: 曾经是persistent状态,现在不在Session缓存中。

  transient 实例通过调用save(), persist() or saveOrUpdate()可以变成persistent实例。persistent实例通过调用delete可以变成transient实例。任何通过get()或者load()方法获取的实例都是persistent实例。detached实例通过调用update(), saveOrUpdate(), lock() or replicate()可以变成persistent实例。transient或者detached实例通过调用merge()方法可以生成一个新的persistent实例,但是并不是他们自己,这个persistent实例是merge方法自己创建的。

  save() 和 persist() 生成SQL insert。delete() 生成SQL delete。update() 和 merge()生成SQL update。对persistent实例的修改在flush时会生成SQL update。saveOrUpdate() 和 replicate()生成insert或者update。

  Session接口的实现类并没有专门设计为线程安全的。相反,每个线程或者事务都应该通过SessionFactory获取自己的实例。

  一个典型的事务应该使用如下的形式:

 Session sess = factory.openSession();
Transaction tx;
try {
tx = sess.beginTransaction();
//do some work
...
tx.commit();
}
catch (Exception e) {
if (tx!=null) tx.rollback();
throw e;
}
finally {
sess.close();
}

  如果Session抛出异常,事务必须回滚。同时Session被弃用,因为Session内部状态和数据库可能会不一致。

1 保存对象到数据库 session.save(Object user); //参数user为transient实例,返回值为新生成的主键id

持久化transient实例。返回值为生成的主键id。

按照第一节的配置,主键的生成策略为native(数据库自动生成主键),由于数据库使用的是mysql 5,所以是自增的主键生成方式。保存对象时并不需要设置id属性。

    @Test
public void testSave() {
try {
User user = new User();
user.setBirthday(new java.sql.Date(0));
user.setName("binyulan");
session.save(user);
} catch (HibernateException e) {
if (transaction != null) {
transaction.rollback();
}
throw e;
}
}

2 保存对象到数据库 session.persist(Object user); //参数user为transient实例

持久化transient实例。这个方法和session.save()方法一样,都是保存对象到数据库。但是不能设置id属性,否则抛出异常。

    @Test
public void testPersist() {
try {
User user = new User();
user.setBirthday(new java.sql.Date(0));
user.setName("binyulan");
user.setId(13);
session.persist(user);
} catch (HibernateException e) {
e.printStackTrace();
if (transaction != null) {
transaction.rollback();
}
throw e;
}
}

执行testPersist后抛出异常,如下:

org.hibernate.PersistentObjectException: detached entity passed to persist: com.binyulan.domain.User
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:139)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:75)

user创建出来为transient实例,但是异常显示是detached实例。所以我认为只要给对象设置了id属性,即使没有持久化过,也可以看做detached实例。

persist()方法的参数为transient实例,即不带主键id的实例。save()方法参数也为transient实例,但是也可以给此实例设置id属性,即detached实例,

只不过此id属性不起作用(native生成方式下)。结论如下:

save()和persist()方法参数虽然都说明为transient实例,但是也可以传detached实例,也可以传persistent实例。但是没有理由传非transient实例,因为这些方法都是设计为传transient实例的,虽然传其他实例也可以,但是不推荐,谁知道100年后hibernate90.10.9会不会改变save()或persist()方法传入非transient实例的行为呢。

3 合并对象到数据库 session.merge(Object user); //参数user为detached实例,其属性将被copy到persistent实例。并且返回此persistent实例

拷贝user到持久化对象。如果没有persistent对象在session缓存中,则加载数据到persistent对象并且返回此persistent对象。

如果user在数据库中没有对应记录,则拷贝user到一个副本作为persistent对象并且返回这个persistent对象。user不会被保存到session缓存中

1) 保存未设置id属性的User对象,执行insert把User对象保存到数据库中,同时返回保存后的User对象。

    @Test
public void testMerge() {
try {
User user = new User();
user.setBirthday(new java.sql.Date(0));
user.setName("binyulan2");
User user1 = (User) session.merge(user); //把user属性拷贝到新建的user1对象,执行insert插入数据库,并且返回新建的user1对象,user1包含id,在session缓存中
System.out.println(user1 == user); //返回false。user为新建的对象,并没有放入session缓存。user1为新建的持久化对象,并且在session的缓存中。
} catch (HibernateException e) {
e.printStackTrace();
if (transaction != null) {
transaction.rollback();
}
throw e;
}
}

2) 保存设置id属性的User对象,首先执行select查询数据库。若数据库中存在此id的记录,并且与数据库中记录不一致,则执行update操作,

若不存在此记录,否则执行insert操作。

    @Test
public void testMerge1() {
try {
User user = new User();
user.setBirthday(new java.sql.Date(0));
user.setName("binyulan123");
user.setId(20);
/**
* 把user属性拷贝到新建的User对象,并且执行select查询数据库。
* 假设数据库中存在id为20的记录,且user对象与数据库中记录不一致,执行update
*/
User user1 = (User) session.merge(user);
System.out.println(user1 == user); //返回false。user为参数,不在session缓存中,user1为新建的持久化对象,并且在session的缓存中。 /**
* 把user属性拷贝到新建的User对象,并且执行select查询数据库。
* 假设数据库中不存在id为123456789的记录,执行insert
*/
user.setId(123456789L);
User user2 = (User) session.merge(user);
System.out.println(user2 == user); //返回false。user为参数,不再session缓存中,user2为新建的持久化对象,并且在session的缓存中。
} catch (HibernateException e) {
e.printStackTrace();
if (transaction != null) {
transaction.rollback();
}
throw e;
}
}

4 数据更新,session.update(Object user);// 参数为一个detached实例。

使用user更新数据库中记录,并且把user对象变为persistent实例。

    @Test
public void testUpdate() {
User user = new User();
user.setName(null);
user.setBirthday(null);
user.setId(20);
session.update(user);
}

5 更新或者保存,session.saveOrUpdate(Object  user);

    @Test
public void testSaveOrUpdate() {
User user = new User();
user.setName(null);
user.setBirthday(null);
session.saveOrUpdate(user); //insert操作 User user1 = new User();
user1.setName(null);
user1.setBirthday(null);
user1.setId(9);
session.saveOrUpdate(user1);//update操作
}

6 删除操作,session.delete(Object user);

从session缓存中删除一个persistent实例。参数为一个Session缓存中的实例或者一个带id的transient实例

    @Test
public void testDelete() {
User user = new User();
user.setId(9);
session.delete(user);
}

7 查询操作,session.get(Class clazz, Serializable id);

根据给定的Class对象和主键id返回persistent实例,如果数据库中没有此记录,则返回null。

    @Test
public void testGet() {
User user = (User) session.get(User.class, 1L);
System.out.println(user);
}

8 查询操作,session.load(Class theClass, Serializable id);

返回一个代理对象,并在访问非主键id属性时会初始化这个代理对象。不能使用这个方法判断是否一个实例存在。即使数据库中没有相应记录,也会返回代理对象,但是在使用此代理对象是就会报错。

@Test
public void testLoad() {
User user = (User) session.load(User.class, 1L); //返回的user为代理对象
user.getName(); //访问name属性时向数据库发送SQL select
System.out.println(user.getClass()); //代理对象类
}

9 复制操作,replicate(Object object, ReplicationMode replicationMode);

    @Test
public void testReplicate() {
User user = new User();
user.setId(48);// 假定数据库中存在id为48的记录
user.setBirthday(new java.sql.Date(0));
user.setName("binyulan1");
/**
* 可以选择复制的模式,OVERWRITE模式为如果存在此记录,则覆盖
* 执行SQL select
*/
session.replicate(user, ReplicationMode.OVERWRITE);
session.flush();// 执行SQL update User user1 = new User();
user1.setId(48);
user1.setBirthday(new java.sql.Date(0));
user1.setName("binyulan2");
/**
* 可以选择复制的模式,IGNORE模式为如果存在此记录,则不进行更新
* 执行SQL select
*/
session.replicate(user1, ReplicationMode.IGNORE);
session.flush();// 记录存在,所以忽略掉,不会执行SQL update User user3 = new User();
user3.setId(48);
user3.setBirthday(new java.sql.Date(0));
user3.setName("binyulan3");
/**
* 可以选择复制的模式,EXCEPTION模式为如果存在此记录,则抛异常
* 此语句执行SQL insert,ReplicationMode.EXCEPTION 始终都会执行SQL insert。
* 使用数据库自身约束抛出异常,因为使用的是native主键生成方式,所以此处不抛异常,会插入成功
*/
session.replicate(user3, ReplicationMode.EXCEPTION);
}

10 强制同步数据到数据库,session.flush();

可以设置FlushMode, 如果设置为NERVER,且不手动执行session.flush(), 提交事务也不会执行SQL update。

System.out.println(session.getFlushMode()); //默认模式为AUTO

    @Test
public void testFlush() {
User user = new User();
user.setId(1); //假设id为1的记录存在
user.setBirthday(new java.sql.Date(0));
user.setName("binyulan3");
session.update(user);
session.flush(); //强制执行SQL update
}

11 同步数据库中数据到java对象,session.refresh(Object user); //参数为persistent实例或者detached实例

重新读取数据库记录到user,不建议在跨多个业务长时间运行的session中使用。在以下特定场景中使用

  1) 触发器出发了一个insert或者update
  2) 执行一大堆sql后
  3) 插入一个Blob或Clob后

@Test
public void testRefresh() {
User user = (User) session.get(User.class, 1L);
user.setName("original");
session.refresh(user); //重新同步数据库中记录到user,此时user的name不是original
System.out.println(user.getName()); // 输出binyulan
}

请勿转载,谢谢合作

原创地址:http://www.cnblogs.com/binyulan/p/5628579.html  

第二节 hibernate session介绍以及session常用方法介绍的更多相关文章

  1. 【hibernate】<第二节>hibernate的一对多映射(基本类型)

    所需工具与前文一致! 第一部分内容:基本类型的一对多(one to many) 以部门表与员工表为例: 目录结构: hibernate.cfg.xml内容 <?xml version=" ...

  2. JPA学习---第二节:JPA开发环境和思想介绍

    一.下载相关 jar http://hibernate.org/orm/ 下载 hibernate ,解压 http://www.slf4j.org/download.html 下载 slf4j,解压 ...

  3. Hibernate学习---Configuration,Session,SessionFactory

    上一节我们讲到了Hibernate的测试,并且给出了测试代码,刚开始看见这个测试代码的同学估计是一头雾水把,所以这一节我们来讲一下测试代码. 本节主要内容: Configuration Session ...

  4. 框架Hibernate笔记系列 基础Session

    标题:框架Hibernate笔记 资料地址: 1. www.icoolxue.com 孔浩 1.背景简介 Hibenate是JBoss公司的产品.它是数据持久化的框架.Usually,我们使用JDBC ...

  5. [原创]java WEB学习笔记94:Hibernate学习之路---session 的管理,Session 对象的生命周期与本地线程绑定

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  6. Spring与Hibernate集成中的Session问题

    主要讨论Spring与Hibernate集成中的session问题 1.通过getSession()方法获得session进行操作 public class Test extends Hibernat ...

  7. ssh中Hibernate懒加载,session问题的学习与理解

    交代本项目中要求获取session的方式如下: public Session getCurrentSession() { // 增删改使用的session,事务必须是开启的(Required,即pro ...

  8. [原创]java WEB学习笔记78:Hibernate学习之路---session概述,session缓存(hibernate 一级缓存),数据库的隔离级别,在 MySql 中设置隔离级别,在 Hibernate 中设置隔离级别

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  9. 【转】介绍设置Session失效的几种方法

    转载地址:http://developer.51cto.com/art/201106/269493.htm Session对象是HttpSessionState的一个实例.该类为当前用户会话提供信息, ...

随机推荐

  1. BW导航属性设置

    BW中的Attribute(属性)分为Display Att.和Navigation(导航) Att.,这里我就简称Dis. att和Nav. att了,导航属性可以做为变量来查询和做限制 1.首先进 ...

  2. Codeforces Gym 100418J Lucky tickets 数位DP

    Lucky ticketsTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view ...

  3. C# 利用范型与扩展方法重构代码

    在一些C#代码中常常可以看到 //An Simple Example By Ray Linn class CarCollection :ICollection { IList list; public ...

  4. cocos2d-x 3.0环境搭建

    原文来自于:http://blog.csdn.net/linzhengqun/article/details/21663341 安装工具 1. 配置JDK JDK下载地址:http://www.ora ...

  5. [Angular 2] Import custom module

    The application structure: in app.module.ts: import { NgModule} from "@angular/core"; impo ...

  6. C++之EOF()

    fstream流的eof()推断有点不合常理 按常理逻辑来说,假设到了文件末尾的话,eof()应该返回真,可是,C++输入输出流怎样知道是否到末尾了呢? 原来依据的是:假设fin>>不能再 ...

  7. Mac OS X 中使用SAP GUI的方法

    下载sap gui for mac 730 解压后 安装之前需要去oracle 官网下载jdk 6 然后运行 安装完成后配置登陆端 新建连接时,只需要配置Advanced 页签:勾选Expert Mo ...

  8. 熟练掌握HDFS的Shell访问

    HDFS设计的主要目的是对海量数据进行存储,也就是说在其上能够存储很大量文件 (可以存储TB级的文件).HDFS将这些文件分割之后,存储在不同的DataNode上, HDFS 提供了两种访问接口:Sh ...

  9. 实验-hadoop开发环境部署

    hadoop-0.20.2自带了eclipse插件,比如1.0.0和2.2.0就没有 1.windows下 1)把插件hadoop-0.20.2-eclipse-plugin.jar复制到eclips ...

  10. iOS “获取验证码”按钮的倒计时功能

    iOS 的倒计时有多种实现细节,Cocoa Touch 为我们提供了 NSTimer 类和 GCD 的dispatch_source_set_timer方法去更加方便的使用计时器.我们也可以很容易的的 ...