Hibernate第四课--HIbernate三大状态转换

来源:互联网 发布:数据统计问题有哪些 编辑:程序博客网 时间:2024/06/10 20:20



瞬时态(Transient):刚new的一个对象(JVM存在,session缓存中没有,数据库不存在)
持久态(Persistent):存储到数据库(JVM存在,session缓存存在,数据库存在)
脱管态(Detached):session缓存关闭(JVM存在,session缓存不存在,数据库存在)

Session方法:

session.save(对象)
@Test
public void testSave() {
System.out.println("================Save start===============");
session.getTransaction().begin();
Student s = new Student();
s.setName("zhansan");
session.save(s);
session.getTransaction().commit();
log.debug("Student "+s);
System.out.println("=================Save end=============");
}

session.delete(对象)
@Test
public void testDelete() {
System.out.println("================Delete start===============");
session.getTransaction().begin();
Student s = new Student();
s.setId(14);
s.setName("zhansan");
session.delete(s);
session.getTransaction().commit();
log.debug("Student "+s);
System.out.println("=================Delete end=============");
}

Load      Student s1=(Student)session.load(Student.class, 1);   //1 是查询Student的条件
 
@Test
public void testLoad() {
System.out.println("================Load start===============");
session.getTransaction().begin();
//第二个参数是一个主键id查询条件
Student s = (Student) session.load(Student.class,15);
session.getTransaction().commit();
/*
* get与load区别:
* get直接查询
* load延迟加载:在需要用到时才加载,如果没有用到就先不加载
*/
//log.debug("Student "+s);
System.out.println("=================Load end=============");
}

Get           Student s1=(Student)session.get(Student.class, 1);
@Test
public void testGet() {
System.out.println("================Get start===============");
session.getTransaction().begin();
//第二个参数是一个主键id查询条件
Student s = (Student) session.get(Student.class,15);
session.getTransaction().commit();
log.debug("Student "+s);
System.out.println("=================Get end=============");
}
getload的区别(面试重点,原理)
1.  不存在对应记录时表现不一样
2.  load返回的是代理对象,等到真正用到对象的内容时才发出sql语句
3.  get直接从数据库加载,不会延迟


updates       session.update(对象);

1.  用来更新detached对象,更新完成后转为persistent状态

2.  更新transient对象会报错

3.  更新自己设定id的transient对象可以(数据库有对应记录)

4.  persistent状态的对象只要设定(如:t.setName…)不同字段就会发生更新

5.  更新部分更改的字段

a)  xml 设定 property 标签的 update 属性,annotation 设定@Column  updatable

   属性,不过这种方式很少用,因为不灵活(忘记)

b)  使用xml中的dynamic-updateJPA1.0 Annotation 没有对应的属性,hibernate 

   展?

i. 同一个session可以,跨session不行,不过可以用merge()(不重要)

c)  使用 HQL(EjBQL)(建议)

@Test
public void testUpdate() {
System.out.println("================Update start===============");
session.getTransaction().begin();
Student s = new Student();
s.setId(15);
s.setName("lisi");
//第二个参数是一个主键id查询条件
session.update(s);
session.getTransaction().commit();
log.debug("Student "+s);
System.out.println("=================Update end=============");
}



session.saveOrUpdate(s);  
存在时,update,不存在时添加
@Test
public void testSaveOrUpdate() {
System.out.println("================Update start===============");
session.getTransaction().begin();
Student s = new Student();
s.setName("saveorupdate");
//注释 下一行 变成插入,不注释变成修改
s.setId(15);
//既可以存入 也可以修改
session.saveOrUpdate(s);
session.getTransaction().commit();
log.debug("Student "+s);
System.out.println("=================Update end=============");
}
clear方法 session.clear();
1.无论是load还是get,都会首先査找缓存(一级缓存),如果没有,才会去数据库査找,调用
clear()方法可以强制清除session缓存

flush()方法 session.flush();
1. 当session的事务提交后,会强制将内存(session缓存)与数据库同步.默认情况下是session的事务提交(commit)时才同步!
2. session的FlushMode设置,可以设定在什么时候同步缓存与数据库(很少用)
例如: session.setFlushMode(FlushMode.AUTO)

@Test
public void testClear_flush() {
System.out.println("================Clear_flush start===============");
session.getTransaction().begin();
 
//既可以存入 也可以修改
Student s = (Student) session.load(Student.class,15);
session.clear();//如果不注释load 缓存中的数据被清除 报错
session.flush();//将数据库缓存commit后都刷入数据库
session.getTransaction().commit();
log.debug("Student "+s);
System.out.println("=================Clear_flush end=============");
}


save和persist的区别
save 把一个临时实例持久化,
因为需要返回一个主键值,因此会立即执行 insert 语句
persist 把一个临时实例持久化标识符
在事务外部调用时则不会立即执行 insert 语句,flush时执行,适用与长事务
在事务内调用还是会立即执行 insert 语句的。
@Test
public void testSave() {
System.out.println("================Save start===============");
System.out.println("begin");
session.getTransaction().begin();
 
Student s = new Student();
s.setName("zhansan");
 
session.save(s);
System.out.println("flush commit");
session.flush();
session.getTransaction().commit();
log.debug("Student " + s);
System.out.println("=================Save end=============");
}
@Test
public void testPesistIn() {
System.out.println("================PesistIn start===============");
Student s = new Student();
s.setName("zhansan");
System.out.println("begin");
session.getTransaction().begin();
session.persist(s);
System.out.println("flush commit");
session.flush();
session.getTransaction().commit();
log.debug("Student " + s);
System.out.println("=================PesistIn end=============");
}
 
@Test
public void testPesistOut() {
System.out.println("================PesistOut start===============");
Student s = new Student();
s.setName("zhansan");
session.persist(s);
System.out.println("begin");
session.getTransaction().begin();
System.out.println("flush commit");
session.flush();
session.getTransaction().commit();
log.debug("Student " + s);
System.out.println("=================PesistOut end=============");
}
输出结果:
================Save start===============
begin
Hibernate: 
    insert 
    into
        Student
        (name) 
    values
        (?)
flush commit
2015-06-30 18:03:42,030 [com.liuhao.hibernate4.demo.coreapi.test.CoreAPITest]-[DEBUG] Student com.liuhao.hibernate4.demo.coreapi.Student@4b82d2[id=26,name=zhansan]
=================Save end=============


================PesistIn start===============
begin
Hibernate: 
    insert 
    into
        Student
        (name) 
    values
        (?)
flush commit
2015-06-30 18:04:17,819 [com.liuhao.hibernate4.demo.coreapi.test.CoreAPITest]-[DEBUG] Student com.liuhao.hibernate4.demo.coreapi.Student@91f005[id=27,name=zhansan]
=================PesistIn end=============

================PesistOut start===============
begin
flush commit
Hibernate: 
    insert 
    into
        Student
        (name) 
    values
        (?)
2015-06-30 18:04:31,715 [com.liuhao.hibernate4.demo.coreapi.test.CoreAPITest]-[DEBUG] Student com.liuhao.hibernate4.demo.coreapi.Student@196e136[id=28,name=zhansan]
=================PesistOut end=============

merge

如果session中存在相同持久化标识(identifier)的实例,用用户给出的对象的状态覆盖旧有的持久实例 
如果session没有相应的持久实例,则尝试从数据库中加载,或创建新的持久化实例,最后返回该持久实例 
用户给出的这个对象没有被关联到session上,它依旧是脱管的 
package comliuhao.hibernate4.demo.function.test;
 
 
import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
 
import com.liuhao.hibernate4.demo.function.Student;
import com.liuhao.hibernate4.demo.uril.HibernateUtil;
 
public class functionTest {
 
private Logger log = Logger.getLogger(functionTest.class);
private static SessionFactory sfactory;
private static Session session;
 
/**
* @throws java.lang.Exception
* @return @void
*/
@Before
public void setUp() throws Exception {
sfactory = HibernateUtil.getSessionFactory();
 
session = sfactory.openSession();
}
 
/**
* @throws java.lang.Exception
* @return @void
*/
@After
public void tearDown() throws Exception {
if (session != null)
session.close();
if (sfactory != null)
sfactory.close();
}
/*
* 准备:数据库存在 id=1的行
* 如果session没有merge(a)对象标识的相同的持久化实例,从数据库加载出实例b,实例b的值从a完全拷贝,最后返回持久化实例b
*
* 控制台输出:
1.session查询同a标识(主键)相同的对象
2. session没有,从数据库查询a标识的字段
Hibernate: select student0_.id as id1_0_0_, student0_.name as name2_0_0_ from
Student student0_ where student0_.id=?
2015-06-30 22:30:26,223 [comliuhao.hibernate4.demo.function.test.functionTest]-[
DEBUG] Student :Student s1 [id=1, name=ssssssssssssss]
3.数据库返回的持久化实例b的值完全从a拷贝,然后返回
2015-06-30 22:30:26,223 [comliuhao.hibernate4.demo.function.test.functionTest]-[
DEBUG] Student :Student s2 [id=1, name=ssssssssssssss]
*/
@Test
public void testMerge() {
session.beginTransaction();
Student s = new Student();
s.setId(1);
s.setName("ssssssssssssss");
Student s2 = (Student)session.merge(s);
log.debug("Student s1 :"+s);
log.debug("Student s2 :"+s2);
session.getTransaction().commit();
session.flush();
}
 
/*
* 如果session中存在相同持久化标识(identifier)的实例,a对象覆盖session中持久化实例值
*
* 控制台输出:
Hibernate: select student0_.id as id1_0_0_, student0_.name as name2_0_0_ from
Student student0_ where student0_.id=?
2015-06-30 22:46:56,520 [comliuhao.hibernate4.demo.function.test.functionTest]-[
DEBUG] Student str2:Student [id=1, name=2222222]
2015-06-30 22:46:56,521 [comliuhao.hibernate4.demo.function.test.functionTest]-[
DEBUG] Student str1:Student [id=1, name=2222222]
*/
@Test
public void testMerge2() {
Student str1 = new Student();
str1.setId(1);
str1.setName("1111111");
session.beginTransaction();
//保证session存在持久化实例
Student str2 = (Student)session.get(Student.class, 1);
str1.setName("2222222");
session.merge(str1);
log.debug("Student str2:"+str2); //这里改变了,说明持久态的数据也会改变
str2.setName("3333333");
log.debug("Student str1:"+str1); //这里不会改变,说明第一个游离态的数据没有被持久化撒;
session.clear();
}
 
}


update与merge区别?
当我们使用update的时候,执行完成后,我们提供的对象A的状态变成持久化状态
但当我们使用merge的时候,执行完成,我们提供的对象A还是脱管状态,hibernate或者new了一个B,或者检索到
一个持久对象B,并把我们提供的对象A的所有的值拷贝到这个B,执行完成后B是持久状态,而我们提供的A还是托管状态
evict
clear完整的清除session缓存
evcit(obj)把某个持久化对象从session的缓存中清空。
refresh
lock


瞬时态(Transient):刚new的一个对象(JVM存在,session缓存中没有,数据库不存在)
持久态(Persistent):存储到数据库(JVM存在,session缓存存在,数据库存在)
脱管态(Detached):session缓存关闭(JVM存在,session缓存不存在,数据库存在)

Session方法:

session.save(对象)
@Test
public void testSave() {
System.out.println("================Save start===============");
session.getTransaction().begin();
Student s = new Student();
s.setName("zhansan");
session.save(s);
session.getTransaction().commit();
log.debug("Student "+s);
System.out.println("=================Save end=============");
}

session.delete(对象)
@Test
public void testDelete() {
System.out.println("================Delete start===============");
session.getTransaction().begin();
Student s = new Student();
s.setId(14);
s.setName("zhansan");
session.delete(s);
session.getTransaction().commit();
log.debug("Student "+s);
System.out.println("=================Delete end=============");
}

Load      Student s1=(Student)session.load(Student.class, 1);   //1 是查询Student的条件
 
@Test
public void testLoad() {
System.out.println("================Load start===============");
session.getTransaction().begin();
//第二个参数是一个主键id查询条件
Student s = (Student) session.load(Student.class,15);
session.getTransaction().commit();
/*
* get与load区别:
* get直接查询
* load延迟加载:在需要用到时才加载,如果没有用到就先不加载
*/
//log.debug("Student "+s);
System.out.println("=================Load end=============");
}

Get           Student s1=(Student)session.get(Student.class, 1);
@Test
public void testGet() {
System.out.println("================Get start===============");
session.getTransaction().begin();
//第二个参数是一个主键id查询条件
Student s = (Student) session.get(Student.class,15);
session.getTransaction().commit();
log.debug("Student "+s);
System.out.println("=================Get end=============");
}
getload的区别(面试重点,原理)
1.  不存在对应记录时表现不一样
2.  load返回的是代理对象,等到真正用到对象的内容时才发出sql语句
3.  get直接从数据库加载,不会延迟


updates       session.update(对象);

1.  用来更新detached对象,更新完成后转为persistent状态

2.  更新transient对象会报错

3.  更新自己设定id的transient对象可以(数据库有对应记录)

4.  persistent状态的对象只要设定(如:t.setName…)不同字段就会发生更新

5.  更新部分更改的字段

a)  xml 设定 property 标签的 update 属性,annotation 设定@Column  updatable

   属性,不过这种方式很少用,因为不灵活(忘记)

b)  使用xml中的dynamic-updateJPA1.0 Annotation 没有对应的属性,hibernate 

   展?

i. 同一个session可以,跨session不行,不过可以用merge()(不重要)

c)  使用 HQL(EjBQL)(建议)

@Test
public void testUpdate() {
System.out.println("================Update start===============");
session.getTransaction().begin();
Student s = new Student();
s.setId(15);
s.setName("lisi");
//第二个参数是一个主键id查询条件
session.update(s);
session.getTransaction().commit();
log.debug("Student "+s);
System.out.println("=================Update end=============");
}



session.saveOrUpdate(s);  
存在时,update,不存在时添加
@Test
public void testSaveOrUpdate() {
System.out.println("================Update start===============");
session.getTransaction().begin();
Student s = new Student();
s.setName("saveorupdate");
//注释 下一行 变成插入,不注释变成修改
s.setId(15);
//既可以存入 也可以修改
session.saveOrUpdate(s);
session.getTransaction().commit();
log.debug("Student "+s);
System.out.println("=================Update end=============");
}
clear方法 session.clear();
1.无论是load还是get,都会首先査找缓存(一级缓存),如果没有,才会去数据库査找,调用
clear()方法可以强制清除session缓存

flush()方法 session.flush();
1. 当session的事务提交后,会强制将内存(session缓存)与数据库同步.默认情况下是session的事务提交(commit)时才同步!
2. session的FlushMode设置,可以设定在什么时候同步缓存与数据库(很少用)
例如: session.setFlushMode(FlushMode.AUTO)

@Test
public void testClear_flush() {
System.out.println("================Clear_flush start===============");
session.getTransaction().begin();
 
//既可以存入 也可以修改
Student s = (Student) session.load(Student.class,15);
session.clear();//如果不注释load 缓存中的数据被清除 报错
session.flush();//将数据库缓存commit后都刷入数据库
session.getTransaction().commit();
log.debug("Student "+s);
System.out.println("=================Clear_flush end=============");
}


save和persist的区别
save 把一个临时实例持久化,
因为需要返回一个主键值,因此会立即执行 insert 语句
persist 把一个临时实例持久化标识符
在事务外部调用时则不会立即执行 insert 语句,flush时执行,适用与长事务
在事务内调用还是会立即执行 insert 语句的。
@Test
public void testSave() {
System.out.println("================Save start===============");
System.out.println("begin");
session.getTransaction().begin();
 
Student s = new Student();
s.setName("zhansan");
 
session.save(s);
System.out.println("flush commit");
session.flush();
session.getTransaction().commit();
log.debug("Student " + s);
System.out.println("=================Save end=============");
}
@Test
public void testPesistIn() {
System.out.println("================PesistIn start===============");
Student s = new Student();
s.setName("zhansan");
System.out.println("begin");
session.getTransaction().begin();
session.persist(s);
System.out.println("flush commit");
session.flush();
session.getTransaction().commit();
log.debug("Student " + s);
System.out.println("=================PesistIn end=============");
}
 
@Test
public void testPesistOut() {
System.out.println("================PesistOut start===============");
Student s = new Student();
s.setName("zhansan");
session.persist(s);
System.out.println("begin");
session.getTransaction().begin();
System.out.println("flush commit");
session.flush();
session.getTransaction().commit();
log.debug("Student " + s);
System.out.println("=================PesistOut end=============");
}
输出结果:
================Save start===============
begin
Hibernate: 
    insert 
    into
        Student
        (name) 
    values
        (?)
flush commit
2015-06-30 18:03:42,030 [com.liuhao.hibernate4.demo.coreapi.test.CoreAPITest]-[DEBUG] Student com.liuhao.hibernate4.demo.coreapi.Student@4b82d2[id=26,name=zhansan]
=================Save end=============


================PesistIn start===============
begin
Hibernate: 
    insert 
    into
        Student
        (name) 
    values
        (?)
flush commit
2015-06-30 18:04:17,819 [com.liuhao.hibernate4.demo.coreapi.test.CoreAPITest]-[DEBUG] Student com.liuhao.hibernate4.demo.coreapi.Student@91f005[id=27,name=zhansan]
=================PesistIn end=============

================PesistOut start===============
begin
flush commit
Hibernate: 
    insert 
    into
        Student
        (name) 
    values
        (?)
2015-06-30 18:04:31,715 [com.liuhao.hibernate4.demo.coreapi.test.CoreAPITest]-[DEBUG] Student com.liuhao.hibernate4.demo.coreapi.Student@196e136[id=28,name=zhansan]
=================PesistOut end=============

merge

如果session中存在相同持久化标识(identifier)的实例,用用户给出的对象的状态覆盖旧有的持久实例 
如果session没有相应的持久实例,则尝试从数据库中加载,或创建新的持久化实例,最后返回该持久实例 
用户给出的这个对象没有被关联到session上,它依旧是脱管的 
package comliuhao.hibernate4.demo.function.test;
 
 
import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
 
import com.liuhao.hibernate4.demo.function.Student;
import com.liuhao.hibernate4.demo.uril.HibernateUtil;
 
public class functionTest {
 
private Logger log = Logger.getLogger(functionTest.class);
private static SessionFactory sfactory;
private static Session session;
 
/**
* @throws java.lang.Exception
* @return @void
*/
@Before
public void setUp() throws Exception {
sfactory = HibernateUtil.getSessionFactory();
 
session = sfactory.openSession();
}
 
/**
* @throws java.lang.Exception
* @return @void
*/
@After
public void tearDown() throws Exception {
if (session != null)
session.close();
if (sfactory != null)
sfactory.close();
}
/*
* 准备:数据库存在 id=1的行
* 如果session没有merge(a)对象标识的相同的持久化实例,从数据库加载出实例b,实例b的值从a完全拷贝,最后返回持久化实例b
*
* 控制台输出:
1.session查询同a标识(主键)相同的对象
2. session没有,从数据库查询a标识的字段
Hibernate: select student0_.id as id1_0_0_, student0_.name as name2_0_0_ from
Student student0_ where student0_.id=?
2015-06-30 22:30:26,223 [comliuhao.hibernate4.demo.function.test.functionTest]-[
DEBUG] Student :Student s1 [id=1, name=ssssssssssssss]
3.数据库返回的持久化实例b的值完全从a拷贝,然后返回
2015-06-30 22:30:26,223 [comliuhao.hibernate4.demo.function.test.functionTest]-[
DEBUG] Student :Student s2 [id=1, name=ssssssssssssss]
*/
@Test
public void testMerge() {
session.beginTransaction();
Student s = new Student();
s.setId(1);
s.setName("ssssssssssssss");
Student s2 = (Student)session.merge(s);
log.debug("Student s1 :"+s);
log.debug("Student s2 :"+s2);
session.getTransaction().commit();
session.flush();
}
 
/*
* 如果session中存在相同持久化标识(identifier)的实例,a对象覆盖session中持久化实例值
*
* 控制台输出:
Hibernate: select student0_.id as id1_0_0_, student0_.name as name2_0_0_ from
Student student0_ where student0_.id=?
2015-06-30 22:46:56,520 [comliuhao.hibernate4.demo.function.test.functionTest]-[
DEBUG] Student str2:Student [id=1, name=2222222]
2015-06-30 22:46:56,521 [comliuhao.hibernate4.demo.function.test.functionTest]-[
DEBUG] Student str1:Student [id=1, name=2222222]
*/
@Test
public void testMerge2() {
Student str1 = new Student();
str1.setId(1);
str1.setName("1111111");
session.beginTransaction();
//保证session存在持久化实例
Student str2 = (Student)session.get(Student.class, 1);
str1.setName("2222222");
session.merge(str1);
log.debug("Student str2:"+str2); //这里改变了,说明持久态的数据也会改变
str2.setName("3333333");
log.debug("Student str1:"+str1); //这里不会改变,说明第一个游离态的数据没有被持久化撒;
session.clear();
}
 
}


update与merge区别?
当我们使用update的时候,执行完成后,我们提供的对象A的状态变成持久化状态
但当我们使用merge的时候,执行完成,我们提供的对象A还是脱管状态,hibernate或者new了一个B,或者检索到
一个持久对象B,并把我们提供的对象A的所有的值拷贝到这个B,执行完成后B是持久状态,而我们提供的A还是托管状态
evict
clear完整的清除session缓存
evcit(obj)把某个持久化对象从session的缓存中清空。
refresh
lock