`

十四、关联关系中的CRUD_Cascade_Fetch

 
阅读更多

1    设定cascade以设定在持久化时对于关联对象的操作(CUD,R归Fetch管)

cascade并不影响读取,fetch才是控制读取


2    cascade仅仅是帮我们省了编程的麻烦而已,不要把它的作用看的太大,建议使用hibernate的cascade注解
a)    Cascade的属性是数组格式,指明做什么操作的时候关联对象是绑在一起的
       cascade={CascadeType.ALL}

CascadeType取值
ALL    Cascade all operations  所有情况
MERGE  Cascade merge operation  合并(merge=save+update)
PERSIST  Cascade persist operation  存储 persist()
REFRESH  Cascade refresh operation  刷新 ,A session里面需要读B session改过之后的数据
REMOVE   Cascade remove operation  删除

铁律:双向关系在程序中要设定双向关联
 铁律:双向mappedBy


3   fetch 

@ManyToOne,在查询的时候默认会把一的一方查询出来,即fetch=FetchType.EAGER

铁律:双向不要两边设置Eager(会有多余的査询语句发出,你取了我,我又会取你)
对多方设置fetch的时候要谨慎,结合具体应用,一般用Lazy不用eager,
特殊情况(多方数量不多的时候可以考虑,提高效率的时候可以考虑)


@OneToMany(mappedBy="group",cascade={CascadeType.ALL}, //控制增删改(即CUD)
                          fetch=FetchType.EAGER //控制查询(即R) EAGER值代表取出关联 LAZY值为不取关联
                          //多的一方fetch取值默认为LAZY 一的一方默认为EAGER
    )
另外:如果User类(即多的一方)中设置fetch=FetchType.LAZY 则在调用多(即Group)的对象值的时候
类似延迟加载 即需要在commit();之前 session还存在时调用 如:
System.out.println(user.getGroup().getName()); 
session.getTransaction().commit();

7    Update时@ManyToOne()中的cascade参数关系
    session.beginTransaction();
    User user = (User)session.load(User.class,1);
    //user对象属性改变 事务commit时自动判断与数据库原有数据不同 可自动update
    //此时的update与@ManyToOne()中的cascade或fetch参数取值无关
    user.setName("user1");
    user.getGroup().setName("group1");
    session.getTransaction().commit();
如果user改变在commit()之后 且想要执行Update方法时 user与group表同时更新则,则User类的cascade={CascadeType.ALL},并在程序中写如下代码:
    session.beginTransaction();
    User user = (User)session.get(User.class,1);
    session.getTransaction().commit();
    user.setName("user1");
    user.getGroup().setName("group1");
    Session session2 = sessionFactory.getCurrentSession();
    session2.beginTransaction();
    session2.update(user);
    session2.getTransaction().commit();
   
8    Delete时@ManyToOne()中的cascade关系
    如果User及Group类中均设为@ManyToOne(cascade={CascadeType.All}),那么在执行如下:
    session.beginTransaction();
    User user = (User)session.load(User.class,1);
    session.delete(user);
    session.getTransaction().commit();
    注意:此处删除的是 多对一(即User对Group) 中的“多”的一方(User类)

会删除user及user对应的group,再反向对应group的user都会删除,原因就是设置了@ManyToOne(cascade={CascadeType.All})

三种方法可避免全部删除的情况:
1.    去掉@ManyToOne(cascade={CascadeType.All})设置;
2.    直接写Hql语句执行删除;
3.    将user对象的group属性设为null,相当于打断User与Group间的关联,代码如下
        session.beginTransaction();
        User user = (User)session.load(User.class,1);
        user.setGroup(null);
        session.delete(user);
        session.getTransaction().commit();
注意:如果删除的是 多对一中的“一”的一方(Group类)时,如果使用第3种方式(user属性设为null)来打断两个对象间的关联的话,代码与之前不同,如下:
    session.beginTransaction();
    Group group = (Group)session.load(Group.class,1);
    //循环将group中的set集合下的各个user对象设为null
    //相当于先将数据库中user表中与group表关联的字段(即groupid)设为null
    for(User user :group.getUsers()){
        System.out.println(user.getName());
        user.setGroup(null);
    }
    //再将group的set集合设为null,相当于将group表中与user表关联的字段(即userid)设为null
    //此句的前提是user表中的关联字段(groupid)已经为null,如没有则相当于破坏了一对多关联,会报错
    group.setUsers(null);
    session.delete(group);
    session.getTransaction().commit();

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics