引言
inverse和cascade都是维护关系的属性。inverse是可以理解为控制反转的意思,而casc理解为级联操作。
inverse
inverse是在一方维护多方的映射文件中才会有,也就是set集合设置的时候,在多方的映射文件中不会出现。当一方的控制权为false的时候,说明控制权还在自己手中,也就是一方可以维护着关系,但当为true的时候,一方将把控制权交给了多方了,导致一方在保存数据维护多方数据时,不会维护这层关系了。通过案例更好的理解。
案例:部门和员工的关系维护。
public class App3_inverse {
private static SessionFactory sf;
static {
sf = new Configuration()
.configure()
.addClass(Dept.class)
.addClass(Employee.class) // 测试时候使用
.buildSessionFactory();
}
// 1. 保存数据
@Test
public void save() {
Session session = sf.openSession();
session.beginTransaction();
// 部门对象
Dept dept = new Dept();
dept.setDeptName("应用开发部");
// 员工对象
Employee emp_zs = new Employee();
emp_zs.setEmpName("张三");
Employee emp_ls = new Employee();
emp_ls.setEmpName("李四");
// 关系
dept.getEmps().add(emp_zs);
dept.getEmps().add(emp_ls); // inverse=true, 不会设置关联。
// 此时的关联应该通过员工方维护。
// 保存
session.save(emp_zs);
session.save(emp_ls);
session.save(dept); // 保存部门,部门下所有的员工
session.getTransaction().commit();
session.close();
}
//2. 是否设置inverse,对获取数据的影响? 无.
@Test
public void get() {
Session session = sf.openSession();
session.beginTransaction();
Dept dept = (Dept) session.get(Dept.class, 1);
System.out.println(dept.getDeptName());
System.out.println(dept.getEmps());
session.getTransaction().commit();
session.close();
}
// 3. 是否设置inverse,对解除关联关系影响?
// inverse=false, 可以解除关联
// inverse=true, 当前方(部门)没有控制权,不能解除关联关系(不会生成update语句,也不会报错)
//
@Test
public void removeRelation() {
Session session = sf.openSession();
session.beginTransaction();
// 获取部门
Dept dept = (Dept) session.get(Dept.class, 2);
// 解除关系
dept.getEmps().clear();
session.getTransaction().commit();
session.close();
}
//3. 是否设置inverse属性,在删除数据中对关联关系的影响?
// inverse=false, 有控制权, 可以删除。先清空外键引用,再删除数据。
// inverse=true, 没有控制权: 如果删除的记录有被外键引用,会报错,违反主外键引用约束!
// 如果删除的记录没有被引用,可以直接删除。
@Test
public void deleteData() {
Session session = sf.openSession();
session.beginTransaction();
// 查询部门
Dept dept = (Dept) session.get(Dept.class, 8);
session.delete(dept);
session.getTransaction().commit();
session.close();
}
}
也就是说,当我们通过一方来set多方额数据,一方维护多方的关系的时候,必须将inverse设置为false,也就是默认值,这样在session操作的时候,才能成功保存对应关系,如果设置为true,控制权交给多方,通过一方保存数据时,外键字段dept_id并没有插入到Employee这张表中,这样关系就会丢失。通过一方保存数据的意思就是通过dept对象来set员工的数据,最后保存的。
总结:
Inverse属性,是在维护关联关系的时候起作用的。
表示控制权是否转移。(在一的一方起作用)
Inverse , 控制反转。
Inverse = false 不反转; 当前方有控制权
True 控制反转; 当前方没有控制权
维护关联关系中,是否设置inverse属性对关联关系是否有影响:
1. 保存数据
有影响。
如果设置控制反转,即inverse=true, 然后通过部门方维护关联关系。在保存部门的时候,同时保存员工, 数据会保存,但关联关系不会维护。即外键字段为NULL
2. 获取数据
没有影响。
3. 解除关联关系?
有影响。
inverse=false, 可以解除关联
inverse=true, 当前方(部门)没有控制权,不能解除关联关系
(不会生成update语句,也不会报错)
4. 删除数据对关联关系的影响?
有影响。
inverse=false, 有控制权, 可以删除。先清空外键引用,再删除数据。
inverse=true, 没有控制权: 如果删除的记录有被外键引用,会报错,违反主外键引用约束! 如果删除的记录没有被引用,可以直接删除。
cascade
cascade 表示级联操作 【可以设置到一的一方或多的一方】
属性设置含义:
none 不级联操作, 默认值
save-update 级联保存或更新
delete 级联删除
save-update,delete 级联保存、更新、删除
all 同上。级联保存、更新、删除
一般是不会用到cascade属性的,因为如果设置一方级联对方,如果不小心删除部门的时候,部门下的所有员工都会被删除,这会造成很大的损失。这里就不在具体说明了。
public class App4_cascade {
private static SessionFactory sf;
static {
sf = new Configuration()
.configure()
.addClass(Dept.class)
.addClass(Employee.class) // 测试时候使用
.buildSessionFactory();
}
// 级联保存
@Test
public void save() {
Session session = sf.openSession();
session.beginTransaction();
// 部门对象
Dept dept = new Dept();
dept.setDeptName("财务部");
// 员工对象
Employee emp_zs = new Employee();
emp_zs.setEmpName("张三");
Employee emp_ls = new Employee();
emp_ls.setEmpName("李四");
// 关系
dept.getEmps().add(emp_zs);
dept.getEmps().add(emp_ls);
// 保存
// session.save(emp_zs);
// session.save(emp_ls);
session.save(dept); // 需要设置级联保存; 保存部门,部门下所有的员工
session.getTransaction().commit();
session.close();
}
// 级联删除
@Test
public void delete() {
Session session = sf.openSession();
session.beginTransaction();
Dept dept = (Dept) session.get(Dept.class,7);
session.delete(dept); // 级联删除
session.getTransaction().commit();
session.close();
}
@Test
public void bak() {
Session session = sf.openSession();
session.beginTransaction();
session.getTransaction().commit();
session.close();
}
}
inverse与cascade区别?
作用的范围不同:
Inverse是设置在集合元素中的。
Cascade对于所有涉及到关联的元素都有效。
<many-to-one/><ont-to-many/>
没有inverse属性,但有cascade属性
执行的策略不同
Inverse 会首先判断集合的变化情况,然后针对变化执行相应的处理。
Cascade 是直接对集合中每个元素执行相应的处理
执行的时机不同
Inverse是在执行SQL语句之前判断是否要执行该SQL语句
Cascade则在主控方发生操作时用来判断是否要进行级联操作
执行的目标不同
Inverse对于<ont-to-many>
和<many-to-many>
处理方式不相同。
对于<ont-to-many>
,inverse所处理的是对被关联表进行修改操作。
对于<many-to-many>
,inverse所处理的则是中间关联表
Cascade不会区分这两种关系的差别,所做的操作都是针对被关联的对象。