Hibernate框架——对象状态

Hibernate对象的状态

应用的场景

假设一个班的所有学生要把考试的成绩同步到数据库表中,如果每一个学生和数据库交互一次,那么有60个学生,则需要更数据库交互60次,但是这样的效率是特别的低,那么怎么处理更加高效呢? 在hibernate中是用什么解决的呢?为了这个问题Hibernate就有了对象状态的这个概念。下面就以我们熟悉的Person表。来进行介绍关于hibernate中对象状态的一些原理。

对象的状态值

在Hibernate中,对象的状态主要由以下几种状态:

  • 临时状态
    刚刚创建的对象
  • 持久状态
    经过session.load(),session.get().session.save(),session.update(),方法都是可以把一个对象转变成托管状态。
  • 脱管状态
    经过session.clear(), session.evict().session.cllose(), 方法可以将一个持久化状态转变成托管状态。

案例一

我们的Person对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.wcc.hibernate.bean;
import java.io.Serializable;
public class Person implements Serializable{
private Long pid;
private String name;
private String description;
public Long getPid() {
return pid;
}
public void setPid(Long pid) {
this.pid = pid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}

HibernateUtils类,用户加载配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.wcc.hibernate.utils;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
* Hibernate的一个取得SessionFactory类
* @author WCC
*
*/
public class HibernateUtils {
public static SessionFactory sessionFactory;
static{
Configuration configuration = new Configuration();
configuration.configure();
sessionFactory = configuration.buildSessionFactory();
}
}

其他的配置文件在 上一篇文章《Hibernate框架——基本操作(一)》中有具体的操作,所以这里就不再用过多的篇幅进行表述,下面直接看测试代码:

1
2
3
4
5
6
7
8
9
10
@Test
public void testSavePerson(){
Session session = HibernateUtils.sessionFactory.openSession();
Person person = new Person();
person.setName("王小虎");
person.setDescription("好帅");
session.save(person);
transaction.commit();
session.close();
}

对于上面的这段代码,要进行的操作是将一条记录保存到数据库中,那么对各条的语句进行对象状态的分析,可以得到如下所示的分析图:

hiernaet中对象转改的变化分析

说明:

  1. 上图中做步骤1,2,3这三个代码对应的操作时,对象的状态称为临时对象,其特征是该对象与hibernate没有关系。
  2. 当执行第4步的时候,person对象由临时状态转化成持久化状态,这个时候数据库没有对应的数据,但是该对象在hibernate内部
  3. 当执行第5步的时候,事务提交了,该对象还是持久化状态的对象,数据库中有对应的值了。
  4. 当执行完第6步的时候,session关闭了,该的对象成为脱管状态的对象。

案例二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
只要一个对象是一个持久化状态的对象,
当事务提交的时候,hibernate内部自动更新
*/
@Test
public void testGetPerson(){
Session session = HibernateUtils.sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
//person为一个持久化状态的对象
Person person = (Person)session.get(Person.class, 1L);
perosn.setName("aaaa");
transaction.commit();
session.close();
}

说明:
1. session.get() 方法提取出来的是一个持久化状态的对象
2. 事务提交的时候,hibernate内部自动更新

案例三

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
对象的副本概念
*/
@Test
public void testGetPerson_2(){
Session session = HibernateUtils.sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
// 产生了一个持久化对象,也产生了一个副本
Person person = (Person)session.get(Person.class, 1L);
/* 由于数据库中存储了这条记录,在
hibernate内部会让person对象对照副本,
如果没有变化,则什么都不做,如果发生改变,
则发出update语句*/
perosn.setName("aaaa");
transaction.commit();
session.close();
}

说明:
在从数据库中取出的记录在hibernate中保存,并且还有一个副本,hibernate对比副本和原纪录,当没有对记录进行修改的操作,就不会进行update的更新操作,这个的操作虽然增加了内存的消耗,但是所以减少了和数据库的交互,以牺牲内存的代价,换取执行的效率。

下面是分析图:
对象副本

案例四

1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
public void testUpdatePerson_2(){
Session session = HibernateUtils.sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
//持久化转态
Person person = (Person)session.get(Person.class, 1L);
perosn.setName("hello");
//把person由持久化转态转变为托管状态
session.evict(person);
session.update(person);//持久化状态
transaction.commit();
session.close();
}

说明:

  1. 该例子中对象的状态经过了由持久化->脱管->持久化的转变
  2. 当事务提交的时候,hibernate内部只管持久化状态的对象,对于临时状态和脱管状态是不管的。

对象转化图

对象转化图

总结

  • 可以通过session.get,session.save,session.update,方法把一个对象变成持久化状态的对象
  • 可以通过session.close session.evict session.clear方法把一个对象变成脱管状态的对象
坚持原创技术分享,您的支持将鼓励我继续创作!