原创地址: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. Hdu 5568 sequence2 高精度 dp

    sequence2 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=556 ...

  2. HDU 1999 不可摸数

    /* 中文题意: 中文翻译: 题目大意:见红字(例如以下) 解题思路:打表,将每一个数的合数之和存在一个数组之中 难点具体解释:用两个for循环写的,第二个for循环主要是解释两个数相乘不超过这个最大 ...

  3. Swift学习笔记(一)搭配环境以及代码执行成功

    1.Swift是啥? 百度去!度娘告诉你它是苹果最新推出的编程语言,比c,c++,objc要高效简单.可以开发ios,mac相关的app哦!是苹果以后大力推广的语言哦! 2.Swift给你带来什么机会 ...

  4. mkimage command not found

    转载:http://blog.csdn.net/armeasy/article/details/6217621 UIMAGE  arch/arm/boot/uImage"mkimage&qu ...

  5. PHP.4-DIV+CSS标准网页布局准备工作(下)

    DIV+CSS标准网页布局准备工作 区块属性(区块模型) 属 性 描 述 Margin(注) 是定义区块外边界与上级元素距离的属性,用1到4个值来设置元素的边界,每个值都是长度.百分比或者auto,百 ...

  6. Jquery 之 日常积累(一)

    1.jquery函数在参数中传递 this,正确的写法: //页面中用 GetString(this); //脚本中定义 function GetString(obj){ var str = $(ob ...

  7. B. Mr. Kitayuta's Colorful Graph

     B. Mr. Kitayuta's Colorful Graph  time limit per test 1 second Mr. Kitayuta has just bought an undi ...

  8. [Java] 多个Map的性能比较(TreeMap、HashMap、ConcurrentSkipListMap)

    比较Java原生的 3种Map的效率. 1.  TreeMap 2.  HashMap 3.  ConcurrentSkipListMap 结果: 模拟150W以内海量数据的插入和查找,通过增加和查找 ...

  9. 给jdk写注释系列之jdk1.6容器(3)-Iterator设计模式

    前面讲了两种List,一种基于数组实现的ArrayList,一种基于链表实现的LinkedList,这两种list是我们工作中最常用到的List容器.当然数组和链表也是两种常见的基本数据结构,其他基本 ...

  10. [改善Java代码]优先使用整型池

    建议28: 优先使用整型池 看如下代码: public class Client { public static void main(String[] args) { Scanner input = ...