前言
算是对spring jpa对象状态的进一步理解吧
spring jpa version:1.10.1
底层hibernate: 5.1.0
场景
从数据库查询出一些任务数据,分发,更改任务状态,执行任务,然后更新任务下次执行时间
遇到的问题
save的时候除了下次执行时间,status字段也被更新了,由于在entity上面使用的dynamic update注解,所以debug看看具体怎么发生的
执行过程
1.一路debug,进入到DefaultMergeEventListener,onMerge(line:64) -> createEntityCopyObserver(line:77) -> onMerge(line:105) 2.在line:144,获取EntityEntry,后续判断,发现对象已经处于游离状态
switch ( entityState ) {
case DETACHED:
entityIsDetached( event, copyCache );
break;
case TRANSIENT:
entityIsTransient( event, copyCache );
break;
case PERSISTENT:
entityIsPersistent( event, copyCache );
break;
default: //DELETED
throw new ObjectDeletedException(
"deleted instance passed to merge",
null,
getLoggableName( event.getEntityName(), entity )
);
}
然后进入到entityIsDetached方法
3.在这个方法里面(依然在DefaultMergeEventListener),line:289,从数据库读了一次,从log也可以看到进行了一次数据库读操作, 到下面的line:326,如下,target是从数据库刚读出来的对象,entity是我们想要进行update的对象,在copyValues的时候,虽然我们只 更新了执行时间,但是这时候2个对象的status值也是不同的,所以target的status被赋予了entity的status值,而这个值是错误的, 所以打印的update sql里面包含了set status=X 的语句
// cascade first, so that all unsaved objects get their
// copy created before we actually copy
cascadeOnMerge( source, persister, entity, copyCache );
copyValues( persister, entity, target, source, copyCache );
//copyValues works by reflection, so explicitly mark the entity instance dirty
markInterceptorDirty( entity, target, persister );
总结
对spring jpa中对象的状态变化不够了解啊,数据查出来后,事务提交,则该对象就变成游离状态了