CascadeType.REFRESH:级联刷新,也就是说,当你刚开始获取到了这条记录,那么在你处理业务过程中,这条记录被另一个业务程序修改了(数据库这条记录被修改了),那么你获取的这条数据就不是最新的数据,那你就要调用实体管理器里面的refresh方法来刷新实体,所谓刷新,大家一定要记住方向,它是获取数据,相当于执行select语句的(但不能用select,select方法返回的是EntityManager缓存中的数据,不是数据库里面最新的数据),也就是重新获取数据。
CascadeType.PERSIST:级联持久化,也就是级联保存。比如保存order的时候也保存orderItem,如果在数据库里已经存在与需要保存的orderItem相同的id记录,则级联保存出错。
CascadeType.MERGE: 级联更新,也可以叫级联合并;比如当对象Order处于游离状态时,对对象Order里面的属性作修改,也修改了Order里面的orderItems。
CascadeType.REMOVE:比如当对Order进行删除操作的时候,也会对orderItems对象进行级联删除操作。
如果在应用中,要同时使用这四项的话,可以改成cascade = CascadeType.ALL
注意: Query query = em.createQuery(“delete from Person o where o.id=?1”);这种删除会不会起作用呢?是不会起作用的,因为配置里那四项都是针对实体管理器的对应的方法。
这里例举一个简单的场景:同时存在三个对象,一个主对象,两个是关联对象,且保存时,是在一个表单中提交时,可以使用。
如上所述,级联的对象会在主对象变更时,也随之变更。
如下的开发场景:
User对象中有关联一个Teacher对象。在编写代码时,关联的时候,为了减少查询,直接获取到id,new出Teacher对象,设置id后,进行关联到User对象上,好处就是减少查询,同时代码简洁。(这里不讨论其他情况)
常见报错信息:
[ERROR]-org.springframework.dao.InvalidDataAccessApiUsageException: Error occurred while storing entity
问题所在就是,对象在缓存中已经存在,现在操作的对象又要对其进行级联分配。所以报两个对象不同,不能复制使用。
解决办法:将关联对象的级联删除去除,即去除CascadeType.MERGE
级联更新的场景有哪些呢?
一般配置为:cascade={CascadeType.REFRESH},fetch=FetchType.LAZY,不会影响系统的正常运作。
不推荐,因为级联删除,删除一个对象,会将关联的对象一并删除了。正常的系统是不会就将数据给物理删除掉的,正确的做法应该是根据逻辑来判断是否能删除,能删除的手动删除即可,不能删除给予相关的提醒即可。