Hibernate报错: org.hibernate.HibernateException: identifier of an instance of XXX was altered from X to X
这个错误是因为Hibernate在保存的时候因为级联保存导致的,我的项目中具体问题如下: 我在保存ServerProduct的时候报错,分析原因如下:
其中我在ProductProject上的限制cascade=CascadeType.ALL意思是级联保存的时候包括全部行为,那么就会级联保存他中的级联类:masterDbaData和backupDbaData。所以会报错user的主键不能又111改成222。
于是还不是很清楚级联更新的我将所有的cascade都改成了cascade = CascadeType.DETACH,这样DETACH就相当于级联evict操作,此时发现虽然不报错了,但是发现保存各个user的信息都是不成功的。
原因:evict方法会从session缓存中清楚当前对象时,会级联清除所有关联对象,所以保存不成功
接下来我又将所有的cascade都改成了cascade = CascadeType.ALL,保存报错,错误类似于:user中的company不为空
原因:当我修改了serverProduct中涉及到人的操作时,比如userA他原来信息会被更新为都为空,因为是级联更新,同时我的这个user类上面company做了限制@NotNull,所有会报错。
最终解决方法:
这样在保存serverProduct的时候会级联保存productProject但是不会去级联保存我们的user类。
总结:
是否级联被注解字段里面的对象。可选值:javax.persistence.CascadeType.PERSIST, MERGE, REMOVE, REFRESH, DETACH, ALL。可选其中的一个或多个,选一个时,花括号可用可不用
PERSIST:级联session的persist操作。假设Student类和teachers字段的@ManyToMany注解上配置有cascade = {CascadeType.PERSIST},那么,当stu1对象set了一个teachers集合(这个集合里面的对象都是瞬态的),持久化这个stu1d对象时,这个集合里面的所有瞬态对象都会被级联持久化到数据库
MERGE:级联merge操作
REMOVE 级联remove操作。
REFRESH 级联refresh操作。
DETACH 级联evict操作。
ALL 级联以上所有操作。