Jimmy Lee Notes Take notes, Reading...

JPA 更新entity

2016-12-05
Jimmy Lee
ORM

前言

算是对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中对象的状态变化不够了解啊,数据查出来后,事务提交,则该对象就变成游离状态了



上一篇 JPA join查询使用

下一篇 经常用到的各种命令


Comments