JPA持久化上下文与对象状态


hibernate 认为一个有id的新对象为detached.

  • 自动脏检查可以通过继承org.hibernate.CustomEntityDirtinessStrategy并设置hibernate.entity_dirtiness_strategy来自定义.

JPA提供一个持久化上下文作为一级缓存,提供自动脏检查.对应某个id的实例在持久化上下文中只有一个对象.
Hibernate,find时总是尝试在当前上下文中先搜索对象,不存在再触发数据库查询.

        Test t1 = em.find(Test.class,1l);
        //query执行前会先flush当前上下文,在查询数据库之后确认对象在当前会话中存在,则直接复用.
        Query query = em.createQuery("from Test where test=:test");
        query.setParameter("test", "fff");
        Test t2 = (Test)query.getSingleResult();
        //确保对象一致性,为true
        System.out.println(t1 == t2);

  • persist,persist的对象不应该为detached(新创建且有id则认为是detached),用于将一个瞬时(无id)/移除对象(有id),变成持久化状态.不适合detached对象,将抛出异常.
  • merge的对象必须为detached/trasiented状态,若为removed则抛出异常.主键生成策略为assigned,则必须使用merge进行持久化.
        
        Test t1 = em.find(Test.class,1l);
        Test t2 = new Test();
        t2.setId(1l);
        //不改变t1的状态,返回一个持久化对象.如果相应id的持久化对象已存在,则直接更新该对象并返回,
        //否则触发数据库查询获得一个持久化对象(若查询结果为空则new创建,并根据主键生成策略决定id值),然后使用t1更新后返回
        Test t3 = em.merge(t1);
        //返回true,直接在已有的持久化对象上更新数据
        System.out.println(t1 == t3);
  • 使用find查找对象
  • 使用getReference来懒加载对象,期间可以使用Hibernate.initialize(obj)进行数据加载,使用PersistenceUnitUtil.isLoaded(obj)来判断该代理是否初始化.
    当entityManager关闭且obj未加载时,则调用obj.attr会抛出异常.
  • 使用remove删除一个对象,对象状态变为removed,只有persist可以将其再次变为持久化对象,使用merge抛出异常.
  • 使用refresh来刷新一个对象,一般不需要
  • detach使一个对象变为托管
  • clear使得上下文所有对象变托管
  • close先执行flush再执行clear

//hibernate的一些有用方法

  • hibernate的replicate用于将一个数据合并到另一张数据表.
EntityManager emA = getDatabaseA().createEntityManager();
Item item = emA.find(Item.class, ITEM_ID);
EntityManager emB = getDatabaseB().createEntityManager();
//IGNORE,如果id冲突则忽略.
//OVERWRITE,如果id冲突则覆盖
//LATEST_VERSION,使用最新数据,对于有version的乐观控制.
//EXCEPTION
emB.unwrap(Session.class).replicate(item, org.hibernate.ReplicationMode.LATEST_VERSION);
  • em.unwrap(Session.class).setDefaultReadOnly(true);将上下文环境设为只读,不再检测脏数据,此时即使调用em.flush()也不会刷新
posted @ 2016-05-25 13:44  fcat  阅读(695)  评论(0编辑  收藏  举报