hibernate 9 使用对象 | hibernate 实战(第二版) 第9章使用对象 | 笔记

本文详细解析持久化声明周期中的四个关键状态:瞬时状态、持久化状态、移除状态和脱管状态,并阐述持久化上下文的作用及持久化上下文管理的对象同一性和等同性。同时对比Hibernate的get()和load()方法的区别,以及在JPA中删除实体的方法与注意事项。最后,讨论单独实例的清除机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1持久化声明周期

对象状态:
1、瞬时状态(新建状态)(临时状态)
瞬时状态其实就是和持久化没啥关系,只是new出来一个类,和数据库也没啥关联,session机制也监控不到。只能等着被
垃圾回收机制回收。

2、持久化状态(托管状态)
就是已经交给容器管理,肯定是已经有和数据库关联的主键。且,目前属于高速缓存状态,容器会检测到实体的数据修改。

3、移除状态(删除状态)
也就是被删除了,session关闭了,他也就等着回收了。

4、脱管状态(游离状态)
大多就是session关闭了,但是对象中还存在和数据库关联的字段。





持久化上下文:
作用:
1、hibernate可以进行自动的脏检查和事务延迟写入。
2、hibernate可以用持久化上下文作为一级高速缓存
3、hibernate可以保证Java对象同一性范围
4、hibernate可以把持久化上下文扩展到跨整个回话。


org.hibernate.event.def.DefaultLoadEventListener
440L(试图找到在session级别的缓存的实体)
Object entity = loadFromSessionCache( event, keyToLoad, options );
然后还会反复寻找各种缓存机制,如果没有,就会调用
return loadFromDatasource(event, persister, keyToLoad, options);


2对象同一性和等同性
对象同一性和等同性:


扩展持久化上下文:




3hibernate接口

hibernate get 和 load 区别

引用 传智:

相同点: 都可以通过指定的实体类与ID从数据库中读取数据,并返回对应的实例,
不同点:
load方法: hibernate认为该id对应的对象(数据库记录)在数据库 中是一定存在的,进而使用代理来延迟加载该对象。在用到该对象中的属性数据时才查询数据库,若查不到,则抛出 ObjectNotFoundEcception 异常.load方法抛异常是指在使用该对象的数据且数据库中不存在该数据时,而不是在创建这个对象时。由于 session 中的缓存对于hibernate来说是个较廉价的资源,所以在load 时会先查一下session缓存看看该id对应的对象是否存在,不存在则创建代理。
get方法: hibernate会确认该id对应的数据是否存在,首先在session 缓存中查找,然后在二级缓存中查找,还没有就查数据库,数据库中没有就返回null。


引用 in action:
get()和load()之间的一个区别在于他们如何表明实例无法被找到。如果数据库中不存在包含给定标示符的行,get()就会返回null。load()方法则抛出一个
ObjectNotFoundException。由你选择喜欢的错误处理方式。
更重要的是,load()方法可能返回一个代理(proxy),一个占位符,而不是命中(hit)数据库。这个结果就是稍后你可能得到一个ObjectNotFoundException,
一旦你试图访问返回的占位符,就立即强制它初始化。(这也称作延迟加载(lazy loading))load()方法始终试图返回一个代理,如果它已经由当前的持久化上下文管理,则返回一个已经初始化的对象实例。get()方法从不返回代理,它始终命中数据库。






merge:作用
  1. privatestaticvoidmerge1() {
  2. Configuration configuration =newConfiguration().configure();
  3. SessionFactory sessionFactory = configuration.buildSessionFactory();
  4. Session session1 = sessionFactory.openSession();
  5. Transaction tr1 = session1.beginTransaction();
  6. TestBean testBean1 = (TestBean) session1.get(TestBean.class,1);
  7. tr1.commit();
  8. session1.close();
  9. testBean1.setPassword("234");
  10. Session session2 = sessionFactory.openSession();
  11. Transaction tr2 = session2.beginTransaction();
  12. TestBean testBean2 = (TestBean) session2.get(TestBean.class,1);
  13. testBean2.setName("hello2");
  14. testBean2.setPassword("456");
  15. //执行update会报错:
  16. //org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session
  17. session2.update(testBean1);
  18. tr2.commit();
  19. session2.close();
  20. sessionFactory.close();
  21. }
  22. privatestaticvoidmerge2() {
  23. Configuration configuration =newConfiguration().configure();
  24. SessionFactory sessionFactory = configuration.buildSessionFactory();
  25. Session session1 = sessionFactory.openSession();
  26. Transaction tr1 = session1.beginTransaction();
  27. TestBean testBean1 = (TestBean) session1.get(TestBean.class,1);
  28. tr1.commit();
  29. session1.close();
  30. testBean1.setPassword("234");
  31. Session session2 = sessionFactory.openSession();
  32. Transaction tr2 = session2.beginTransaction();
  33. TestBean testBean2 = (TestBean) session2.get(TestBean.class,1);
  34. testBean2.setName("hello2");
  35. testBean2.setPassword("456");
  36. TestBean testBean3 = (TestBean)session2.merge(testBean1);
  37. System.out.println(testBean1);
  38. System.out.println(testBean2);
  39. System.out.println(testBean3);
  40. //打印如下(testBean2的hello2的name属性改变被覆盖了):
  41. //TestBean [id=1, name=hello, password=234]
  42. //TestBean [id=1, name=hello, password=234]
  43. //TestBean [id=1, name=hello, password=234]
  44. //Hibernate: update Test_Bean set name=?, password=? where id=?
  45. tr2.commit();
  46. session2.close();
  47. sessionFactory.close();
  48. }




session.setFlushMode()






4JPA


删除区别:
在hibernate中,下面的方法是ok的
  1. privatestaticvoiddelete() {
  2. Configuration configuration =newConfiguration().configure();
  3. SessionFactory sessionFactory = configuration.buildSessionFactory();
  4. Session session = sessionFactory.openSession();
  5. Transaction tr = session.beginTransaction();
  6. TestBean testBean =newTestBean();
  7. testBean.setId(1);
  8. session.delete(testBean);
  9. tr.commit();
  10. session.close();
  11. sessionFactory.close();

在JPA中:
  1. privatestaticvoiddelete() {
  2. EntityManagerFactory factory = Persistence.createEntityManagerFactory("partner4java");
  3. EntityManager em = factory.createEntityManager();
  4. EntityTransaction tr = em.getTransaction();
  5. tr.begin();
  6. TestBean testBean =newTestBean();
  7. testBean.setId(1);
  8. //报错(不能一个托管在状态的实体调用remove):Removing a detached instance
  9. em.remove(testBean);
  10. tr.commit();
  11. em.close();
  12. factory.close();
  13. }

应该:
  1. privatestaticvoiddelete2() {
  2. EntityManagerFactory factory = Persistence.createEntityManagerFactory("partner4java");
  3. EntityManager em = factory.createEntityManager();
  4. EntityTransaction tr = em.getTransaction();
  5. tr.begin();
  6. em.remove(em.getReference(TestBean.class,2));
  7. tr.commit();
  8. em.close();
  9. factory.close();
  10. }



单独实例的清除?hibernate利用evict(object),jpa不存在这种规范。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值