zoukankan      html  css  js  c++  java
  • hibernate cascade的真正含义

    hibernate cascade 是 @OneToOne @OneToMany @ManyToOne @ManyToMany等注解的属性,表示级联操作。

      /**
         * (Optional) The operations that must be cascaded to
         * the target of the association.
         *
         * <p> By default no operations are cascaded.
         */
        CascadeType[] cascade() default {};

    谷歌翻译对注释的翻译

    必须级联到关联目标的操作。默认情况下没有级联操作。

    这里解释一下,级联的意思是:本实体做了什么事,也要拉上 另一个关联的实体,导致另一个实体跟着做事情。就是说我删除了,你也得删除! 关联目标,指的是 关联的那个实体。

    在有中间关系表的情况下,比如 user/role/user_role 这三张表,只对应User/Role两个实体对象就够了!中间表是由User对象或者Role对象维护的,不用另外新建user_role的实体!

    user

    id name

    role

    id name

    user_role

    user_id role_id

    @Table(name = "user")
    @Entity
    public class User
    {
        @ManyToMany(fetch = FetchType.LAZY)
        @JoinTable(name = "user_role", joinColumns = {@JoinColumn(name= "user_id")}, inverseJoinColumns = {@JoinColumn(name = "role_id")})
        private Set<Role> roles;
    
    
        //get set ...
    }
    @Entity
    @Table(name = "role")
    public class Role
    {
    
        @ManyToMany(fetch= FetchType.LAZY)
        @JoinTable(name = "user_role", joinColumns = {@JoinColumn(name= "role_id")}, inverseJoinColumns = {@JoinColumn(name = "user_id")})
        private Set<User> users;
    
        // get set ...
    
    }

    上述是对user,role多对多的关联关系的配置。cascade没有写,即是默认值,就是不级联的意思。

    不级联就是说,比如在User类中,@ManyToMany没有写cascade就是说,User的操作不影响Role的操作,也就是说针对user表的操作不影响role表的记录。这个和user_role关系表没关系!user_role表的映射关系的维护,和cascade写不写,写什么值一点关系都没有!hibernate会给你维护好关系表的记录的,经测试是先删除关系记录,再插入关系记录。

    如果,你发现User针对Role属性的cascade没有写,但是修改了role的值,确发生变更了,打印出sql语句,也发现还是级联更新了,咋回事?

    这个我也郁闷了好久,hibernate真心不好用,太复杂了。经过苦心调试终于明白了。不是cascade不写没有用,而是你对role的变更是不是先查询出来的持久对象的操作。这样的操作是针对Role持久化对象的修改,和级联没关系,就是说你直接修改了role对象,当然更新了值!

    Set<Role> roles = new HashSet<>();           
    for (Long roleId : roleIds)
    {
           Role role = roleDAO.get(Role.class, roleId);
           role.setName(role.getName()+"_1"); //测试级联
           roles.add(role);
    }
    user.setRoles(roles);
    userDao.saveOrUpdate(user);

    上述代码,保存user的时候,即使cascade没有写,可是role记录还是被改变了!原因就是,你通过roleId得到Role的时候,得到的是Role持久化对象,然后你改变了Role的值,那role记录肯定变更了!这个变更和cascade没有关系,是你自己变更的,能怪谁!请看下述代码

    Set<Role> roles = new HashSet<>();           
    for (Long roleId : roleIds)
    {
           Role role = roleDAO.get(Role.class, roleId);
           role.setName(role.getName()+"_1"); //测试级联
           session.evict(role); //使持久化对象游离
           roles.add(role);
    }
    user.setRoles(roles);
    userDao.saveOrUpdate(user); 

    这里就增加了一句代码,再运行,你会发现,Role值改变了,确实没有使role记录发生变更,这说明cascade不写有用了。这时,你把User类下roles属性上的casecase改为CascadeType.ALL,再运行你会发现,role记录又改变了,那这次role的变更才是真正因为是cascade的作用!

    总结:

    1.hibernate实体关系中,cascade属性表示 实体的操作是否 级联 到 关联的实体, 和中间表无关。

    2.无论cascade写不写,写什么, 中间表都将被hibernate很好的维护了。

    3.cascade不写,没有生效,可能是因为你直接对 关联的实体(持久化的对象) 进行操作了,游离化的 对象就不会有事!

    所以说,如果你如果不想让Role的修改影响到User,那你cascade就不要写,针对User的操作也要注意不要使用持久化的对象(get,load得到的对象,hql得到的是游离化的对象),反之亦然。不用担心中间表的关系维护! 如果你想让Role的修改影响到User,那你就写上cascade的值,级联就生效了(user对象管它是持久对象还是游离对象)!

    附录:

    /**
     * Defines the set of cascadable operations that are propagated
     * to the associated entity.
     * The value <code>cascade=ALL</code> is equivalent to
     * <code>cascade={PERSIST, MERGE, REMOVE, REFRESH, DETACH}</code>.
     *
     * @since Java Persistence 1.0
     */
    public enum CascadeType {
    
        /** Cascade all operations 级联所有操作 */
        ALL,
    
        /** Cascade persist operation 级联新增 */
        PERSIST,
    
        /** Cascade merge operation 级联更新或者新增 */
        MERGE,
    
        /** Cascade remove operation 级联删除 */
        REMOVE,
    
        /** Cascade refresh operation 级联刷新 */
        REFRESH,
    
        /**
         * Cascade detach operation
         * 级联分离
         * @since Java Persistence 2.0
         *
         */
        DETACH  
    }
  • 相关阅读:
    Head First设计模式之组合模式
    Html input 常见问题
    Head First设计模式之外观模式
    Head First设计模式之适配器模式
    Head First设计模式之模板方法模式
    VS2013 VS2015 VS2017调试出现无法启动iis express web服务器
    win7经常出现“关闭xxxx前您必须关闭所有会话框”
    微信小程序开发之scroll-view
    HTML5在线预览PDF
    JQuery中根据属性或属性值获得元素
  • 原文地址:https://www.cnblogs.com/hdwang/p/7241043.html
Copyright © 2011-2022 走看看