hibernate-实体类状态
来源:互联网 发布:微信群淘宝优惠券代理 编辑:程序博客网 时间:2024/06/17 01:45
前言
hibernate 拿起来用简单,但是用起来很扎心,经常报一些不能理解的错误。很大因素是我不理解 hibernate。hibernate 中的实体类有三大状态:瞬时状态(transient),持久化状态(persistent),游离状态(detached)。理解了这三个状态,就可知道调用一个方法,究竟发了几条 sql ,干了些什么。
瞬时状态: 不在 session 缓存中,没有保存在数据库中
持久化状态: 在 session 缓存中(被 session 托管),保存在数据库中
游离状态:不在 session 缓存中,保存在数据库中(离线状态)
PS: hibernate 二级缓存(session 缓存)是默认开启的,在向数据库查询时先查看会缓存中有没有。
各种状态转换:
结论
1.瞬时状态,游离状态,相当于一个普通对象,没有被 session 托管,操作不影响数据库。
2.持久化状态,在 session 缓存中,被 session 托管,相关操作会影响数据库
测试
实体类
@Entity@Table(name = "t_user")public class UserEntity { private Long id; private String name; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public Long getId() { return id; } public String getName() { return name; } public void setId(Long id) { this.id = id; } public void setName(String name) { this.name = name; }}
1.如何维护 GenerationType.IDENTITY 策略 (主键自增ID)
插入一个 user ,不设置主键ID值,发出sql: Hibernate: insert into t_user (name) values (?)
Session session = HibernateUtil.openSession(); session.beginTransaction(); UserEntity userEntity = new UserEntity(); userEntity.setName("xioamo"); session.save(userEntity); session.getTransaction().commit();
插入一个 user , 设置主键ID值,发出 sql: Hibernate: insert into t_user (name) values (?)
Session session = HibernateUtil.openSession(); session.beginTransaction(); UserEntity userEntity = new UserEntity(); userEntity.setName("xiaoming"); userEntity.setId(100); session.save(userEntity); session.getTransaction().commit();
通过测试可以知道,无论是都指定主键ID的值,都不会把id 值拼接到 sql 中,也就是说主键自增ID策略,完全交给 mysql 自己来处理。你无法指定特定的主键ID。
2.瞬时状态,离线状态对象通过 setters 方法修改对象属性,不会更新到数据库。持久化状态通过通过 setters 方法修改对象属性,会更新到数据库。
userEntity 为瞬时状态,调用setters 控制台没有发出 sql
Session session = HibernateUtil.openSession();session.beginTransaction();UserEntity userEntity = new UserEntity();userEntity.setName("xiaomo");session.getTransaction().commit();
save(userEntity) 后 userEntity 转为持久化状态。发出sql: Hibernate: insert into t_user (name) values (?)
Session session = HibernateUtil.openSession();session.beginTransaction();UserEntity userEntity = new UserEntity();userEntity.setName("xiaomo");session.save(userEntity);session.getTransaction().commit();
在 save 后 userEntity 是持久状态,修改属性,发现发出一条 update sql
sql:
Hibernate: insert into t_user (name) values (?)
Hibernate: update t_user set name=? where id=?
Session session = HibernateUtil.openSession();session.beginTransaction();UserEntity userEntity = new UserEntity();userEntity.setName("xiaomo");session.save(userEntity);userEntity.setName("xiaoming");session.getTransaction().commit();
相对于上面的例子在事务提交前调用 clear 清除缓存,转换为游离状态,发现没有再发出 update sql。
sql:
Hibernate: insert into t_user (address, email, name) values (?, ?, ?)
Session session = HibernateUtil.openSession();session.beginTransaction();UserEntity userEntity = new UserEntity();userEntity.setName("xiaomo");session.save(userEntity);userEntity.setName("xiaoming");session.clear();session.getTransaction().commit();
通过对比上面例子可以说明,在事务提交前 hibernate 会比对持久化状态的对象,发现当前对象内容反生改变(实际上当前对象和 session 缓存的对象是同一个,至于如何发现对象内容发生改变还没有理解清楚),则会以当前对象为准更新到数据库。而对于瞬时状态和游离状态的对象则不作处理。
3.在会话中多次save 或 update ,其运行结果:
Hibernate: insert into t_user (name) values (?)
UserEntity{id=15, name=’xiaomo’}
UserEntity{id=15, name=’xiaohong’}
Hibernate: update t_user set name=? where id=?
Session session = HibernateUtil.openSession(); session.beginTransaction(); UserEntity userEntity = new UserEntity(); userEntity.setName("xiaomo"); session.save(userEntity); System.out.println(session.get(UserEntity.class,userEntity.getId())); userEntity.setName("xiaoming"); session.save(userEntity); userEntity.setName("xiaohong"); session.update(userEntity); System.out.println(session.get(UserEntity.class,userEntity.getId())); session.getTransaction().commit();
从上面的测试可以发现只发出了两条 sql ,对于持久化状态的对象,调用 save 或 update 是不起作用的,而是在事务提交前检查对象是否改变,若改变则更新到数据库,通过这样来维护数据库与 session 缓存对象的一致性,大概更高效吧。
4.执行 update(),只会把对象由非持久状态(如果是非持久状态)转换为持久化状态,真正的 update sql 是在事务提交时发出的。
结果:
before update run
after update run
Hibernate: update t_user set name=? where id=?
Session session = HibernateUtil.openSession();session.beginTransaction();UserEntity userEntity = new UserEntity();userEntity.setId(2l);System.out.println("before update run");session.update(userEntity);System.out.println("after update run");session.getTransaction().commit();
小结:当前被操纵的 java 实体类对象,如果是瞬时状态或者游离状态,则此时没有与数据库关联,如果是持久化状态,该对象(其实就是session缓存的对象)与session 相关联,改变对象属性会更新到数据库。更新到数据库是发生在事务提交的时候。
以上是单表的测试,可以合理猜测在关联表中,实体类,关联实体类的都几个状态转换与含义都一样的。
- hibernate-实体类状态
- hibernate中实体类对象状态
- hibernate实体类的三种状态
- hibernate实体类状态之间转换
- Hibernate实体状态
- hibernate中的实体状态
- hibernate实体状态
- hibernate实体状态
- hibernate-4-实体状态
- hibernate 实体状态转移
- 问题:Hibernate中的实体状态
- Hibernate中的实体状态【转】
- Hibernate实体对象四大状态
- Hibernate中的实体状态(二)
- Hibernate中的实体状态(一)
- hibernate中实体类的三种状态
- hibernate中实体类的三种状态
- Hibernate实体类对象生命周期的3种状态
- c++重载,重写,重定义的区别???
- hibernate-基本用法2
- 对于IE兼容的简单解决办法,【相对复杂的定制网页除外】
- get和post的区别
- SSH与SSM学习之Spring01——介绍、搭建环境与第一个例子
- hibernate-实体类状态
- String转StringBuffer以及String[ ]之间的相互转换
- XPDF安装与使用说明
- hibernate-使用data jpa
- 使用Spring Cloud Consul实现服务的注册和发现
- 西雅图的房子加价到底有多狠?
- 没有相爱,只有相杀:微软和谷歌又撕上了...
- SSH与SSM学习之Spring02——bean元素配置
- java中的Iterator和Iterable 区别