JPA实体状态学习-(瞬时态:Transient)

Entity instance states

为了学习实体的状态,我们还是贴出这张实体状态转换迁移图:

Transient(瞬时态)

按照上图的描述,java对象在内存中被赋值后,没有调用entityManager.persist()方法之前实体对象所处的状态。

举个例子:

Teacher teacher = new Teacher("email@dot.com");

此时,实例teacher就处于new/transient态(备注:这里的new和transient是同一个意思

 

Persistent(持久态)

掌握这个状态,需要记住一句关键的话:

An Object that is associated with persistence context (hibernate session) are in Persistent state. Any changes made to objects in this state are automatically propagated to databases without manually invoking persist/merge/remove

与持久上下文关联的对象处于持久态。任何对这个对象属性的更改都会自动传播到数据库而不需手动调用persist/merge/remove方法。(备注:这里的关联的意思就是说实体对象被持久上下文管理,也有的翻译将这个状态称作托管态)

代码举例:

这里我们还是用代码来说明:

**
 * 测试保存,验证持久态的数据更新
 */
public void saveTeacher() {
    Teacher teacher = new Teacher("new_email@gmail.com");
    logger.info("teacher: {} is transient state",teacher);
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    EntityTransaction tx = entityManager.getTransaction();
    tx.begin();
    entityManager.persist(teacher);
    logger.info("teacher: {} is persistent state",teacher);
    teacher.setEmail("updated_email@gmail.com");
    Long persistedId = teacher.getId();
    logger.info("teacher: {} has changed email",teacher);
    tx.commit();
    entityManager.close();
    logger.info("teacher: {} is detached state",teacher);
    entityManager = entityManagerFactory.createEntityManager();
    tx = entityManager.getTransaction();
    tx.begin();
    teacher = entityManager.find(Teacher.class, persistedId);
    tx.commit();
    entityManager.close();
    logger.info("Persisted teacher: {}", teacher);
}

下面截取出相应的日志信息来分析问题:

teacher: Student{id=null, email='new_email@gmail.com'} is transient state
Hibernate: 
   call next value for hibernate_sequence
teacher: Student{id=1, email='new_email@gmail.com'} is persistent state
teacher: Student{id=1, email='updated_email@gmail.com'} has changed email
Hibernate: 
   insert 
   into
       teachers
       (email, id) 
   values
       (?, ?)
Hibernate: 
   update
       teachers 
   set
       email=? 
   where
       id=?
teacher: Student{id=1, email='updated_email@gmail.com'} is detached state
Hibernate: 
   select
       teacher0_.id as id1_0_0_,
       teacher0_.email as email2_0_0_ 
   from
       teachers teacher0_ 
   where
       teacher0_.id=?
Persisted teacher: Student{id=1, email='updated_email@gmail.com'}

日志分析:

以上的日志说明了一个teacher对象从transient----->persistent----->detached 过程中,SQL语句的执行情况:

执行persist()到持久态后执行一条insertSQL语句;

当改变持久态对象的属性时会执行一条update语句,这两条语句显然都是tx.commit()后才发出;

最后发出一个select语句来查询数据库中最终的teacher对象,用于验证之前的结论。

管理这一过程的就是持久化上下文。

我们测试在detached态时修改对象的状态有啥不一样:

/**
 * 测试保存,验证持久态的数据更新
 */
public void saveTeacher() {
    Teacher teacher = new Teacher("new_email@gmail.com");
    logger.info("teacher: {} is transient state",teacher);
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    EntityTransaction tx = entityManager.getTransaction();
    tx.begin();
    entityManager.persist(teacher);
    logger.info("teacher: {} is persistent state",teacher);
    teacher.setEmail("updated_email@gmail.com");
    Long persistedId = teacher.getId();
    logger.info("teacher: {} has changed email",teacher);
    tx.commit();
    //增加了这一行代码后
    teacher.setEmail("updated_email1@gmail.com");
    entityManager.close();
    logger.info("teacher: {} is detached state",teacher);
    entityManager = entityManagerFactory.createEntityManager();
    tx = entityManager.getTransaction();
    tx.begin();
    teacher = entityManager.find(Teacher.class, persistedId);
    tx.commit();
    entityManager.close();
    logger.info("Persisted teacher: {}", teacher);
}

这里我只截取部分输出,能够看到结果表明原理就好

teacher: Student{id=1, email='updated_email1@gmail.com'} is detached state

Persisted teacher: Student{id=1, email='updated_email@gmail.com'}

可以知道,detached状态的对象属性email已经改变成updated_email1@gmail.com,但是从数据库查询数来的值没有改变,还是updated_email@gmail.com

结论说明

  • Detached状态的实体属性改变不会同步更新数据库
  • Persistent状态的实体属性改变会同步更新数据库

下一篇,我会尝试用代码来说明其他实体状态的迁移,欢迎大家多多分享和交流。

 

版权声明:著作权归作者所有。

相关推荐

JPA实体状态学习-(游离态:Detached)

今天我们学习另一种实体状态,老规矩还是先上图:Detached(游离态 unmanaged)An Object becomes detached when the currently running Persistence Context is closed. Any changes made to detached objects are no longer automatically prop

JPA实体状态学习-(持久态:Persistent)

今天我们继续学习JPA的实体状态转化,老规矩贴上实体转化的转化图: 上一节我们学习了:entityManager调用persist()方法后,实体的状态从transient到persistent,这个时候对persistent状态的实体改变也会同步持久化到数据库,执行tx.commit()之后实体进入detached状态,此时对实体进行改变后不会同步到数据库。今天我们来看看transie

JPA实体状态深入理解

我们在学习JPA实体状态的时候,常常会问,JPA的实体有多少状态呢?相信这个问题不难回答:瞬时态(transient)托管态(persistent)游离态(detached)移除态(removed)注意:这里最后一个移除态,有的时候也叫删除态(deleted),至于它和移除态有啥区别,暂时没有想到,如果您对此有更加深刻的理解,请留言回复。为什么会有这四种状态呢?啥,这个也有为啥,网上不是都这么说的

获取curl的http response状态码

可以使用以下脚本获取curl请求返回的状态码:curl -w '%{response_code}\n' -so /dev/null $URL其中$URL是一个变量,可以使用实际测试的url替换。如请求百度:curl -w '%{response_code}\n' -so /dev/null https://baidu.com输出结果:302

thenjs 学习

thenjs 是一个js的异步控制流程库 特点 可以像标准的Promise那样,把N多异步回调函数写成一个长长的then链,并且比Promise更简洁自然。因为使用标准Promise的then链,其中的异步函数都必须转换成Promise,Thenjs则无需转换,像使用CallBack一样执行异步函数即可。 强大的Error机制,可以捕捉任何同步和异步的异步错误。 开启debug模式

Android保存及恢复Activity的状态

Android保存Activity状态有两种方式:activity保存以及持久化保存。这里主要介绍activity保存。保存Activity状态基于Activity保存状态需要重写onSaveInstanceState(Bundle savedInstanceState)方法。示例:@Override public void onSaveInstanceState(B