学习hibernate时对级联关系的概念老是分不清楚,尤其是cascade、inverse以及mappedBy的作用。下面通过例子来简单说明。
准备工作
首先创建数据库,新建两张表:
教室表cr,字段如下
学生表student,字段如下:
教室与学生是一对多的关系。
然后新建项目,添加hibernate支持,由于inverse是hbm.xml配置文件中的属性,而mappedBy是注解中的属性,因此分开说明。
cascade属性
cascade用于指示级联关系,即两个实体间存在级联关系(一个类是另一个类中的属性)时,当保存、更新或删除一个实体时,是否对关联的实体做出相应操作(数据库操作),例如
<hibernate-mapping>
<class name="model.Cr" table="cr" catalog="hbmtest">
<id name="id" type="integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="cname" type="string">
<column name="cname" length="20" />
</property>
<set name="students" inverse="true">
<key>
<column name="crid" />
</key>
<one-to-many class="model.Student" />
</set>
</class>
</hibernate-mapping>
上面是cr表的映射配置,执行如下测试代码
Session session = HibernateSessionFactory.getSession();
session.beginTransaction();
Student stu = new Student();
stu.setName("zhu");
Cr cr = new Cr();
cr.setCname("cname");
Set<Student> set = new HashSet<Student>();
set.add(stu);
cr.setStudents(set);
stu.setCr(cr);
session.save(cr);
session.getTransaction().commit();
执行上面代码后,数据表cr中插入一行,而student表未变化。而将上面的配置改为
<set name="students" cascade="all" inverse="true">后,执行上述代码则student表会有数据插入。
inverse
inverse属性用于指示本方是否参与维护关系,设为true时不维护,设为false时维护。此处的关系是指关联两张表的
外键或者关系表字段。本属性一般设置于一对多关系中的一端,并且设置为false,因为若由一端负责维护,每次更新完一端数据,都会去寻找于一端有关系的多段表中的行,并更新其外键字段。而由多端维护时,由于一端对象是多端对象的属性字段,所以,每次更新多端后提交数据,都会自动更新该字段(若有更新时),这样比较方便。
<hibernate-mapping>
<class name="model.Cr" table="cr" catalog="hbmtest">
<id name="id" type="integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="cname" type="string">
<column name="cname" length="20" />
</property>
<set name="students" cascade="all" inverse="true">
<key>
<column name="crid" />
</key>
<one-to-many class="model.Student" />
</set>
</class>
</hibernate-mapping>
执行以下测试代码:
Session session = HibernateSessionFactory.getSession();
session.beginTransaction();
Student stu = new Student();
stu.setName("zhu");
Cr cr = new Cr();
cr.setCname("cname");
Set<Student> set = new HashSet<Student>();
set.add(stu);
cr.setStudents(set);
session.save(cr);
session.getTransaction().commit();
结果
:
cr表
student表
由上图可以看出,由于cr不负责维护关系,所以插入一条cr数据后虽然在student插入一行,但其外键为null。当更改inverse为false或默认设置时,结果会更新student表的crid字段。
mappedBy
mappedBy属性用于注解中,作用与inverse类似,不过其值必须为多端对象中对应一端对象的成员变量名。当设置后,由多端维护关系,未设置时,hibernate会去寻找由student的id字段和cr的id字段组成的关系表,如果未建立该表会报错。为了避免报错并且由两端同时维护关系,可以在一端加上@JoinColumn(name="多端外键字段名"),这样作用就等同于inverse=false了。
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name="crid")
public Set<Student> getStudents() {
return this.students;
}
Session session = HibernateSessionFactory.getSession();
session.beginTransaction();
Student stu = new Student();
stu.setName("zhu");
Cr cr = new Cr();
cr.setCname("cname");
Set<Student> set = new HashSet<Student>();
set.add(stu);
cr.setStudents(set);
session.save(cr);
session.getTransaction().commit();
执行结果未两张表均插入一行,而且student表中的外键不为空。
如果您觉得这文章对您有帮助,可以打赏点钱给我,鼓励我继续写博,我的支付宝