对象状态:
一般来说,new 出来的与 session 没有关联,是瞬时状态。但是,如果故意地将 new 出来的一个对象按照数据库中的某条记录赋值,那么这个对象也就成为脱管状态,因为已经有数据和它对应了。可以直接用这个对象对数据库进行对应记录的 delete、update 操作。并且,delete 和 update 的时候,只要主键与数据库中的记录相同即可,其他属性不需要相同。
实验:
public static void main(String[] args) {
Session s = HibernateUtil. getSession();
StudentInfo studentInfo = new StudentInfo();
studentInfo.setBirthday( new Date());
studentInfo.setName( "Gong");
addStudentInfo( studentInfo);
System. out.println( "id="+ studentInfo.getId()); // 保存时,由于主键自动生成,因此 id 自动被赋值
StudentInfo studentInfo2 = new StudentInfo(); // 新建一个对象,并且按照刚刚插入进去的记录的主键进行赋值,其他属性不同。
studentInfo2.setBirthday( new Date());
studentInfo2.setName( "Gong222");
studentInfo2.setId(1);
updateStudentInfo( studentInfo2);
studentInfo = getStudentInfo( studentInfo.getId());
System. out.println( "id="+ studentInfo.getId()+ ",name="+ studentInfo.getName());
s.close();
System. out.println( "end");
}
结果输出如下:
Hibernate:
insert
into
StudentInfo
(name, birthday)
values
(?, ?)
id=1
Hibernate:
update
StudentInfo
set
name=?,
birthday=?
where
id=?
Hibernate:
select
studentinf0_.id as id0_0_,
studentinf0_.name as name0_0_,
studentinf0_.birthday as birthday0_0_
from
StudentInfo studentinf0_
where
studentinf0_.id=?
id=1,name=Gong222
end
可以看到,当 update 的时候,生成的sql语句直接根据主键来定位。
另一个实验:
public static void main(String[] args) {
Session s = HibernateUtil. getSession();
StudentInfo studentInfo = new StudentInfo();
studentInfo.setBirthday( new Date());
studentInfo.setName( "Gong");
addStudentInfo( studentInfo);
System. out.println( "id="+ studentInfo.getId()); // 保存时,由于主键自动生成,因此 id 自动被赋值
StudentInfo studentInfo2 = new StudentInfo(); // 新建一个对象,并且按照刚刚插入进去的记录的主键进行赋值,其他属性不同。
studentInfo2.setBirthday( new Date());
studentInfo2.setName( "Gong222");
studentInfo2.setId(1);
deleteStudentInfo( studentInfo2); // 删除
studentInfo = getStudentInfo( studentInfo.getId());
System. out.println( studentInfo);
s.close();
System. out.println( "end");
}
运行结果:
Hibernate:
insert
into
StudentInfo
(name, birthday)
values
(?, ?)
id=1
Hibernate:
delete
from
StudentInfo
where
id=?
Hibernate:
select
studentinf0_.id as id0_0_,
studentinf0_.name as name0_0_,
studentinf0_.birthday as birthday0_0_
from
StudentInfo studentinf0_
where
studentinf0_.id=?
null
end
可以看到,主键为 1 的记录已经被删除,查询不到。
因此,辨别一个对象是瞬时状态还是游离状态,关键是看它的主键是否在数据库记录中。如果在,就是游离状态,否则是瞬时状态。其实实际增删改查时,并不需要有瞬时还是游离的概念。
关键是要判断出是不是持久状态,因为持久状态的话,修改对象的值,Hibernate会记下来,在
事务提交的时候,所有修改都会同步到数据库中。也就是说,对数据库的修改有延迟,不会每次修改对象,都会同步到数据库中,在事务提交的时候才会。