原创地址: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. BZOJ 3170: [Tjoi 2013]松鼠聚会 切比雪夫距离

    3170: [Tjoi 2013]松鼠聚会 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/p ...

  2. [Javascript] Manipulate the DOM with the classList API

    Learn how to add, remove and test for CSS classes using the classList API. It's more powerful than u ...

  3. iOS小结

    一.内存管理情况 1- autorelease,当用户的代码在持续运行时,自动释放池是不会被销毁的,这段时间内用户可以安全地使用自动释放的对象.当用户的代码运行告一段 落,开始等待用户的操作,自动释放 ...

  4. PHP获取解析URL方法

    们要经常对url里面所带的参数进行解析,如果我们知道了url传递参数名称,例如: /index.php?name=tank&sex=1#top 我们就可以通过$_GET['name'],$_G ...

  5. Computer Science Theory for the Information Age-4: 一些机器学习算法的简介

    一些机器学习算法的简介 本节开始,介绍<Computer Science Theory for the Information Age>一书中第六章(这里先暂时跳过第三章),主要涉及学习以 ...

  6. strassen algorithm

    the explaination that is clear in my view is from wiki.

  7. BEA WebLogic Server 10 查看和配置日志

    查看和配置日志 WebLogic Server 内的每个子系统都可生成日志消息来传达其状态.例如,当启动 WebLogic Server 实例时,安全子系统会输出消息以报告其初始化状态.为了记录其子系 ...

  8. 我cnblogs的主题

    我的cnblogs主题 这里记录的是本博客的主题存档 主题代码参考自:流云诸葛的博客 博客皮肤选择 选择 LessIsMore 页面定制CSS代码 div.post div.entry { font- ...

  9. eclipse按Crl+鼠标左键,找不到源文件的解决办法。

    这种情况一般发生在tomcat的之中,原因是缺少类的源文件.在jdk中很少见,jdk中自带类的源文件,配置jdk的时候就已经将其加载进来了.而tomcat之中没有带类的源文件,需要自己去网上单独下载. ...

  10. Android(java)学习笔记112:局部位置的内部类的介绍

    1.局部内部类 /* 局部内部类 A:可以直接访问外部类的成员 B:在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能 面试题: 局部内部类访问局部变量的注意事项? A:局部 ...