实际操作中经常会碰到多表查询,那么多表查询Hibernate是怎么做处理的呢?
假设有两个实体:客户(Customer)和联系人(LinkMan),一个客户对应多个联系人;
1、在类中添加关系
Customer类中添加:
//new的作用是让linkmans不为空
//0的作用是让其在内存中不占用空间
private Set<LinkMan> linkmans=new HashSet<LinkMan>(0);
LinkMan类中添加:
private Customer customer;
自动补全这俩个类的get和set方法。
2、修改配置文件
修改LinkMan.hbm.xml:
<!-- 一对多关系映射:从表实体映射配置
涉及标签:
mangy-to-one:
作用:建立多对一的映射配置
属性:
name:从表实体中引用主表实体类对象的引用名称
class:指定属性所对应的实体类名称
column:指定从表中外键字段的名称
inverse定义:是否放弃维护关联关系的权利
true:放弃
false:默认值,不放弃
-->
<many-to-one name="customer" class="Customer" column="主键id" inverse="true"></many-to-one>
修改Customer.hbm.xml
<!--一对多关系映射:主表实体的映射配置
涉及的标签:
set:
作用:用于配置set集合属性
属性:
name:指定实体类中set集合的属性名称
table:指定从表的名称,在一对多配置时可以不写;
key:
作用:用于映射外键字段;
属性:
column:指定外键字段名称;
one-to-many:
作用:用于建立一对多的映射配置
属性:
class:用于指定从表实体的名称
-->
<set name="linkmans" table="cst_linkman">
<key column="lkm_cust_id"></key>
<one-to-many class="LinkMan"></one-to-many>
</set>
3、级联保存
保存操作中有一类,称为级联保存;
级联保存的配置方式,仍然是找到Customer的映射配置文件的Set标签
在上面加入cascade属性:级联保存更新数据的取值:save-update
<set name="linkmans" table="cst_linkman" inverse="true" cascade="save-update">
Demo:
//级联更新操作
public void test()
{
Session s=HibernateUtil.getCurrentSession();
Transaction tx=s.beginTransaction();
//查询一个客户
Customer c1=s.get(Customer.class,1L);
//创建一个新的联系人
LinkMan l=new LinkMan();
l.setLkmName("一对多联系人");
//建立客户和联系人的关系(双向)
l.setCustomer(c1);
c1.getLinkmans().add(l);
//更新客户
s.update(c1);
tx.commit();
}
4、删除操作
删除操作:删除从表数据就是单表
删除主表的话,就得看有没有从表数据的引用
如果有引用,在删除是,Hibernate会把从表中的外键字段置为null,然后再删除主表数据;如果外键字段有非空约束,则Hibernate不能更新外键字段为null,会报错;如果没有引用,就是单表,直接删除;
在实际开发中,级联删除要慎重,因为一旦事务提交了,就能难再找回数据了。
Tips:1、多对多关系时,在俩个表中的类配置中添加set(前文已有代码),记得各个表的主键名称到别的表做外键时,需要保持一致,不然会创建多个外键;
2、实际开发当中,多对多的双向级联删除是禁止的。