脏对象:在Seesion管理的持久化对象中,该对象的数据和数据库中的数据不一致,此对象是脏对象。
刷新缓存:Session是提供持久化操作的主要接口,Session具有一个缓存,可以管理和跟踪所有持久化对象。在某些时间点,Session会根据缓存中对象的变化执行相关SQL语句将对象发生的变化同步到数据库中,就是说将数据库的数据同步与Seesion缓存一致。这过程是刷新缓存。
脏检查:在刷新缓存之前Session会进行脏检查,当持久化对象加入Session缓存中时,Session会对持久化对象进行快照。操作中,持久化对象的属性发生改变变成脏对象时,Session就会将脏对象与快照进行对比,此过程称为脏检查。随后就进行刷新缓存操作使数据库中的数据与脏对象同步。
/**
* 测试刷新缓存
*/
public void flush(Serializable id)
{
Transaction tx=null;
Department department=null;
try {
tx=departmentDao.getCurrentSession().beginTransaction();
department=departmentDao.load(id);
department.setLocation("西部");//修改操作脏数据
System.out.println(department+"是脏对象");
//脏检查和刷新缓存
tx.commit();
System.out.println("完成脏检查和刷新缓存");
}catch (HibernateException ex)
{
ex.printStackTrace();
if(tx!=null)
{
tx.rollback();
}
}
}
Session进行刷新缓存的方式
- 1.显式调用Session的flush()方法时。Session的flush()方法进行刷新缓存的操作会触发脏检查,依据情况来执行相关SQL语句进行同步。
- 2.调用Transaction的commit()时即提交事务时。commit()方法会先调用Session的刷新缓存方法flush(),然后向数据库提交事务。在提交事务时候执行刷新缓存的动作可以减少访问数据库的频率,尽可能缩短书屋对数据库中相关资源的锁定时间。
Hibernate API更新数据
update()方法,用于将游离状态的对象转为持久状态,同时进行数据库更新操作。当参数的对象OID为null时会报异常。
saveOrUpdate()方法,同时包含了save()和update()方法的功能,如果传入参数是瞬时状态的对象,就调用save()方法;如果传入参数是游离状态的对象,则调用update()方法。
merge()方法,能够把作为参数传入的游离状态对象的属性复制到一个拥有相同OID的持久状态对象中,通过对持久化状态对象的脏检查实现更新操作,并返回该持久化对象;如果无法从Session缓存或数据库加载到相应的持久状态对象,即传入的是瞬时对象,则创建其副本执行插入操作,并返回一新的持久状态对象。无论何种情况,传入对象状态都不受影响。
//实现部门的更新
public void update(Department department) {
this.getCurrentSession().update(department);
}
public void updateDept(Department department) {
Transaction tx = null;
Department result = null;
Department temp = null;
try {
tx = departmentDao.getCurrentSession().beginTransaction();
/*Department dept = departmentDao.get(department.getDeptNo());
dept.setDeptName("销售部");
dept.setLocation("东莞");*/
departmentDao.update(department);
result = departmentDao.load(department.getDeptNo());
System.out.println(result.getDeptName());
tx.commit();
} catch (HibernateException ex) {
ex.printStackTrace();
if (tx != null) {
tx.rollback();
}
}
}
@Test
public void update() {
Department department = new Department();
// department.setDeptNo((byte)10);
department.setDeptNo((byte) 12);
department.setDeptName("市场部");
department.setLocation("东部");
departmentBiz.updateDept(department);
}
update()方法传入的是瞬时状态对象,传入参数转为持久化对象
Hibernate:
update
project.Department
set
deptName=?,
location=?
where
deptNo=?
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
update()方法传入的是游离状态对象,传入的参数转为持久化对象
Hibernate:
update
project.Department
set
deptName=?,
location=?
where
deptNo=?
/**
* 测试saveOrUpdate()方法
*/
public void saveOrUpdate(Department department)
{
this.getCurrentSession().saveOrUpdate(department);
}
public void saveOrUpdateDept(Department department) {
Transaction tx = null;
Department result = null;
Department temp = null;
try {
tx = departmentDao.getCurrentSession().beginTransaction();
departmentDao.saveOrUpdate(department);
result = departmentDao.load(department.getDeptNo());
System.out.println(result.getDeptName());
tx.commit();
} catch (HibernateException ex) {
ex.printStackTrace();
if (tx != null) {
tx.commit();
}
}
}
@Test
public void saveOrUpdate() {
Department department = new Department();
department.setDeptNo((byte) 15);
department.setDeptName("研发部");
department.setLocation("西部");
departmentBiz.saveOrUpdateDept(department);
}
saveOrUpdate()方法传入参数是瞬时状态对象,传入的参数转为持久化对象
Hibernate:
select
department_.deptNo,
department_.deptName as deptName0_,
department_.location as location0_
from
project.Department department_
where
department_.deptNo=?
教育部
Hibernate:
update
project.Department
set
deptName=?
where
deptNo=?
saveOrUpdate()方法传入参数是游离状态对象,传入参数转为持久化对象
Hibernate:
select
department_.deptNo,
department_.deptName as deptName0_,
department_.location as location0_
from
project.Department department_
where
department_.deptNo=?
教育部
Hibernate:
insert
into
project.Department
(deptName, location, deptNo)
values
(?, ?, ?)
/**
* 测试merge()方法
*/
public Department merge(Department department)
{
return (Department) this.getCurrentSession().merge(department);
}
public void mergeDept(Department department) {
Transaction tx = null;
Department result = null;
Department temp = null;
Department newDept = null;
try {
tx = departmentDao.getCurrentSession().beginTransaction();
newDept=departmentDao.merge(department);
result = departmentDao.load(department.getDeptNo());
System.out.println(result.getDeptName());
tx.commit();
} catch (HibernateException ex) {
ex.printStackTrace();
if (tx != null) {
tx.rollback();
}
}
}
@Test
public void merge() {
Department department = new Department();
department.setDeptNo((byte) 18);
department.setDeptName("研发部");
department.setLocation("西部");
departmentBiz.mergeDept(department);
}
merge()方法传入的是瞬时状态对象,传入参数对象还是瞬时状态对象,返回的对象是持久化状态
Hibernate:
select
department0_.deptNo as deptNo0_0_,
department0_.deptName as deptName0_0_,
department0_.location as location0_0_
from
project.Department department0_
where
department0_.deptNo=?
研发部
Hibernate:
insert
into
project.Department
(deptName, location, deptNo)
values
(?, ?, ?)
merge()方法传入的是游离状态对象,传入参数还是游离对象,返回的对象是持久化对象
Hibernate:
select
department0_.deptNo as deptNo0_0_,
department0_.deptName as deptName0_0_,
department0_.location as location0_0_
from
project.Department department0_
where
department0_.deptNo=?
教育部
Hibernate:
update
project.Department
set
deptName=?
where
deptNo=?
总结update(),saveOrUpdate(),merge()更新数据的方法的区别
update()方法是使游离对象转为持久化对象,当传入的参数是瞬时状态的对象即没有OID时会抛出异常,而且执行update()方法后的传入参数的对象是持久化对象。
saveOrUpdate()方法可以使瞬时状态和游离状态对象转为持久化对象,在更新数据之前saveOrUpdate方法会select查询数据库判断传入的参数是什么对象,如果是瞬时对象执行insert语句,如果是游离对象执行update语句,而且执行完saveOrUpdate方法后传入的参数对象转为持久化对象。
merge()方法和saveOrUpdate()方法一样也是可以使瞬时状态和游离状态对象转为持久化对象,在更新数据之前也会select查询数据库判断传入参数对象是说明对象,如果是瞬时状态执行insert,游离执行update。但是不同于saveOrUpdate方法是传入参数的对象状态不会改变。如果传入对象状态时游离,执行完merge还是游离对象,瞬时状态也一样。但是merge()方法有返回值返回的对象时持久化对象。由于Session接口一级缓存原因所以merge方法多次从数据库查询的数据都会从数据库中取,而saveOrUpdate方法是从Session对象中取数据。