Session 的主要功能是为映射实体类的实例提供创建,读取和删除操作。这些实例可能在给定时间点时存在于以下三种状态之一:
- 瞬时状态: 一种新的持久性实例,被 Hibernate 认为是瞬时的,它不与 Session 相关联,在数据库中没有与之关联的记录且无标识符值。临时状态对象是通过实例化的方式注入到内存中,也就是通过New的方式来开辟内存。临时对象是孤立在内存上的,它不与数据库中的数据有任何关系。
- 持久状态:可以将一个瞬时状态实例通过与一个 Session 关联的方式将其转化为持久状态实例。持久状态实例在数据库中没有与之关联的记录,有标识符值,并与一个 Session 关联。通过session.get()或者session.load()等获取的数据对象,就是持久化状态的对象。注意:如果对持久化对象进行了修改,并没有执行事务提交,这时持久化对象的数据不会同步到数据库中的。
- 脱管状态:一旦关闭 Hibernate Session,持久状态实例将会成为脱管状态实例。
下面我们通过几个例子来了解下这三种状态的区别。
临时状态
@Test
public void test3() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = new Student();
student.setName("王五");
student.setAge("22");
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
刚实例化的实体是临时状态,在session中不存在,也没有和数据库进行关联。所以执行事务提交没有任何语句打印。
@Test
public void test3() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = new Student();
student.setName("王五");
student.setAge("22");
session.save(student);
session.saveOrUpdate(student);
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
临时状态的对象我们可以通过save()或者saveOrUpdate()方法将对象从临时状态转换为持久态。注意:执行saveOrUpdate()时,session里的实例没有任何变化,所以在提交时只打印一次插入语句。
@Test
public void test3() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = new Student();
student.setName("王五");
student.setAge("22");
session.save(student);
student.setName("王老五");
session.saveOrUpdate(student);
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
当执行保存操作后,再次修改实体里面的属性值,saveOrUpdate()会执行更新操作,在提交事务时会先执行插入语句,再执行更新语句。
持久状态
@Test
public void test1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = session.get(Student.class, "402899816753f99f016753f9a2df0000");
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
通过session.get()、session.load()、query.list()、query.iterate()可以获取持久状态的实例或者实例集合。注意:query.list()、query.iterate()方法必须用实体接收才是持久状态,这也很好理解,映射实体类的实例才有三种状态的说法。
@Test
public void test1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = session.get(Student.class, "402899816753f99f016753f9a2df0000");
student.setName("王四");
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
注意:持久状态的数据是和数据库有同步关联,对持久态的数据进行操作需要特别注意,修改了数据后就算不执行更新操作,在事务提交时也会修改数据库的数据,这是因为在事务提交时进行了flush操作。这也许就是在日常使用中数据无端被改的原因。
脱管状态(游离态)
@Test
public void test4() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = session.get(Student.class, "402899816753f99f016753f9a2df0000");
student.setName("wangsisi");
session.evict(student);
System.out.println(student.getName());
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
@Test
public void test5() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = session.get(Student.class, "402899816753f99f016753f9a2df0000");
student.setName("wangsisi");
session.clear();
System.out.println(student.getName());
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
当数据为持久态时,修改实体里面的属性值,在事务提交的时候会更新数据库。现在我们在事务提交前执行evict()和clear()操作,发现并没有打印更新语句。这时实例处于脱管状态,即虽然实例有数据库标识值 id,但是在session缓存中不存在与之对应的实例。当然在事务提交时,就无法从session中取出操作计划对数据库进行操作。
脱管状态》持久状态
@Test
public void test4() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = session.get(Student.class, "402899816753f99f016753f9a2df0000");
student.setName("wangsisi");
session.evict(student);
session.update(student);
session.saveOrUpdate(student);
System.out.println(student.getName());
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
通过update()、saveOrUpdate()方法可以使实例从脱管状态转换成持久态,实例变为持久态后,事务提交时就会执行更新操作,打印一条update语句。还有一种lock操作也可以使实例从脱管状态转换成持久态。后面我们再单独讲解。
脱管状态》临时状态 持久状态》临时状态
@Test
public void test6() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = session.get(Student.class, "402899816753f99f016753f9a2df0000");
session.delete(student);
student.setName("ssngag");
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
通过delete()方法可以使实例从脱管状态或持久状态转换成临时状态。
@Test
public void test6() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = session.get(Student.class, "40289981675e6ea701675e6eaabc0000");
session.delete(student);
session.save(student);
session.getTransaction().commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
在delete()方法后面增加保存操作,这时在删除操作后会增加插入操作,这是因为虽然session缓存里面已经没有了这个实例,但是虚拟机内存里面实例还是存在的。