关系标签
- one-to-one:标签不影响存储,只影响加载,不会修改数据库,也就是说不会添加字段
- many-to-one:一般在程序中表现为子表对象里存储一个主表对象,会修改数据库,会增加一个字段
级联操作
cascade:级联的意思是指定两个对象之间的操作联动关系,对一个对象执行了操作之后,对其指定的级联对象也需要执行相同的操作。
其属性值如下:
1. all:在所有的情况下都执行级联操作
2. none:在所有情况下都不执行级联操作
3. save-update:在保存和更新的时候执行级联操作
4. delete:在删除的时候执行级联操作
5.
单向n对1
public class OrderEntity {
private int id;
private String orderName;
private CustomerEntity customerEntity;
...
}
<class name="OrderEntity" table="orders" schema="test">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="orderName" column="orderName"/>
<!--
customerEntity属性的主键id参照orders表生成字段customerId查询,并且加入外键:customerEntity.id = customerId
-->
<many-to-one name="customerEntity" class="CustomerEntity" column="customerId"/>
</class>
public class CustomerEntity {
private int id;
private String customerName;
...
}
<class name="CustomerEntity" table="customer" schema="test">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="customerName" column="customerName"/>
</class>
插入操作:
// add
OrderEntity order = new OrderEntity();
order.setOrderName("test_order1");
OrderEntity order2 = new OrderEntity();
order2.setOrderName("test_order1");
CustomerEntity customer = new CustomerEntity();
customer.setCustomerName("test_customer2");
order.setCustomerEntity(customer);
order2.setCustomerEntity(customer);
// 3条insert,推荐插入顺序
session.save(customer);
session.save(order);
session.save(order2);
// 3条insert(customer为null)+2条update
session.save(order);
session.save(order2);
session.save(customer);
查询+更新操作:
// 查询,默认延迟加载,使用到代理对象的时候才会进行初始化
OrderEntity orderEntity = session.get(OrderEntity.class, 2);
// customerEntiy 代理对象
// update
orderEntity.setOrderName("hahaha");
orderEntity.getCustomerEntity().setCustomerName("ooooo");
删除分级联情况考虑。
双向1对n
public class CustomerEntity {
private int id;
private String customerName;
// 防止空指针
private Set<OrderEntity> orders = new HashSet<>();
...
}
<class name="CustomerEntity" table="customer" schema="test">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="customerName" column="customerName"/>
<!--使用额外java属性:set集合,查询orders表,以 orders.customerId = CustomerEntity.id 作为查询条件-->
<!--inverse="true":主动方维护关系,推荐-->
<!--inverse="false":被动方维护关系-->
<!--不设置inverse,两边都维护-->
<!--cascade="delete"级联删除-->
<set name="orders" table="orders" inverse="true" cascade="delete" order-by="orderName desc">
<key column="customerId"/>
<one-to-many class="OrderEntity"/>
</set>
</class>
orderEntity相同,插入操作
OrderEntity order = new OrderEntity();
order.setOrderName("test_order1");
OrderEntity order2 = new OrderEntity();
order2.setOrderName("test_order2");
CustomerEntity customer = new CustomerEntity();
customer.setCustomerName("test_customer2");
order.setCustomerEntity(customer);
order2.setCustomerEntity(customer);
customer.getOrders().add(order);
customer.getOrders().add(order2);
// 3条insert+2条update,推荐插入顺序
// 设定inverse="true",3条insert
session.save(customer);
session.save(order);
session.save(order2);
查询+更新操作
// select
CustomerEntity customerEntity=session.get(CustomerEntity.class,1);
//代理对象
System.out.println(customerEntity.getOrders().getClass().getName());
// 延迟加载
System.out.println(customerEntity);
OrderEntity orderEntity=new OrderEntity();
orderEntity.setOrderName("SDA");
session.save(orderEntity);
orderEntity.setCustomerEntity(customerEntity);
customerEntity.getOrders().add(orderEntity);
customerEntity.setCustomerName("nimab");
删除操作相同
基于外键的1对1映射关系
存在外键的一端使用,不存在外键的一端使用
public class DepartmentEntity {
private int id;
private String departmentName;
private Integer managerId;
private ManagerEntity managerEntity;
...
}
<!-- 存在外键 DepartmentEntity.managerId = ManagerEntity.id -->
<class name="DepartmentEntity" table="department" schema="test">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="departmentName" column="departmentName"/>
<!--
managerEntity的主键id参照department表生成字段managerId查询,并且生成外键:
department.managerId = managerEntity.id
-->
<many-to-one name="managerEntity" class="ManagerEntity" column="managerId" cascade="all"
unique="true"/>
</class>
public class ManagerEntity {
private int id;
private String managerName;
private DepartmentEntity departmentEntity;
...
}
<!--不存在外键,主键被DepartmentEntity.managerId参考-->
<class name="ManagerEntity" table="manager" schema="test">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="managerName" column="managerName"/>
<!--
不生成额外字段和外键
departmentEntity的主键id参考DepartmentEntity的managerEntity属性的主键id
departmentEntity.id = DepartmentEntity.managerEntity.id = department.managerId
-->
<one-to-one name="departmentEntity" class="DepartmentEntity" property-ref="managerEntity"/>
</class>
插入操作:
DepartmentEntity departmentEntity = new DepartmentEntity();
departmentEntity.setDepartmentName("hashh");
ManagerEntity managerEntity = new ManagerEntity();
managerEntity.setManagerName("test");
managerEntity.setDepartmentEntity(departmentEntity);
departmentEntity.setManagerEntity(managerEntity);
session.save(departmentEntity);
System.out.println(departmentEntity.getId());
session.save(managerEntity);
查询+更新操作:
// 查询,延迟加载
DepartmentEntity departmentEntity = session.get(DepartmentEntity.class, 1);
System.out.println(departmentEntity.getManagerEntity().getManagerName());
ManagerEntity managerEntity = session.get(ManagerEntity.class, 1);
System.out.println(managerEntity.getDepartmentEntity().getDepartmentName());
managerEntity.setManagerName("whf");
departmentEntity.setDepartmentName("jd");
基于主键的1对1映射关系
两个表的主键完全相同,只需要one-to-one标签
<!-- 存在外键 DepartmentEntity.id = ManagerEntity.id -->
<class name="DepartmentEntity" table="department" schema="test">
<id name="id" column="id">
<!--参考managerEntity的主键id-->
<generator class="foreign">
<param name="property">managerEntity</param>
</generator>
</id>
<property name="departmentName" column="departmentName"/>
<!--
不生成额外字段
生成外键:ManagerEntity.id = DepartmentEntity.id
DepartmentEntity的主键id参考ManagerEntity的主键id
-->
<one-to-one name="managerEntity" class="ManagerEntity" constrained="true"/>
</class>
<!--不存在外键,主键id被DepartmentEntity.id参考-->
<class name="ManagerEntity" table="manager" schema="test">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="managerName" column="managerName"/>
<!--
不生成额外字段和外键
ManagerEntity的主键id参考DepartmentEntity的主键id
不指定property-ref,默认参照departmentEntity.id
ManagerEntity.id = DepartmentEntity.id
-->
<one-to-one name="departmentEntity" class="DepartmentEntity"/>
</class>
单向n对n关系映射
<class name="CatagoryEntity" table="catagory" schema="test">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="catagoryName" column="catagoryName"/>
<set name="items" table="catagoryitem">
<!--CatagoryEntity参考中间表catagoryitem的cataId字段-->
<key column="cataId"/>
<!--ItemEntity参考中间表catagoryitem的itemId字段 -->
<many-to-many class="ItemEntity" column="itemId"/>
</set>
</class>
public class CatagoryEntity {
private int id;
private String catagoryName;
private Set<ItemEntity> items = new HashSet<>();
...
}
<class name="n2n.ItemEntity" table="item" schema="test">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="itemName" column="itemName"/>
</class>
public class ItemEntity {
private int id;
private String itemName;
...
}
插入操作:
CatagoryEntity catagoryEntity1 = new CatagoryEntity();
catagoryEntity1.setCatagoryName("cataName1");
CatagoryEntity catagoryEntity2 = new CatagoryEntity();
catagoryEntity2.setCatagoryName("cataName2");
ItemEntity itemEntity1 = new ItemEntity();
itemEntity1.setItemName("itemName1");
ItemEntity itemEntity2 = new ItemEntity();
itemEntity2.setItemName("itemName2");
catagoryEntity1.getItems().add(itemEntity1);
catagoryEntity1.getItems().add(itemEntity2);
catagoryEntity2.getItems().add(itemEntity1);
catagoryEntity2.getItems().add(itemEntity2);
session.save(catagoryEntity1);
session.save(catagoryEntity2);
session.save(itemEntity1);
session.save(itemEntity2);
双向n对n关系映射
<class name="ItemEntity" table="item" schema="test">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="itemName" column="itemName"/>
<!--两端必须有一端使用inverse="true",否则关系维护失败:主键重复-->
<set name="catagorys" table="catagoryitem" inverse="true">
<key column="itemId"/>
<many-to-many class="CatagoryEntity" column="cataId"/>
</set>
</class>
<class name="CatagoryEntity" table="catagory" schema="test">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="catagoryName" column="catagoryName"/>
<set name="items" table="catagoryitem">
<!--CatagoryEntity参考中间表catagoryitem的cataId字段-->
<key column="cataId"/>
<!--ItemEntity参考中间表catagoryitem的itemId字段 -->
<many-to-many class="ItemEntity" column="itemId"/>
</set>
</class>
Subclass继承关系映射
父类与子类共用一张表
<!--PeopleEntity设定辨别列的值为people-->
<class name="PeopleEntity" table="people" schema="test"
discriminator-value="people">
<id name="id" column="id">
<generator class="native"/>
</id>
<!--数据表的type字段为辨别列-->
<discriminator column="type"/>
<property name="peopleName" column="peopleName"/>
<!--StudentEntity设定辨别列的值为student,使用hql的表名为StudentEntity-->
<subclass name="StudentEntity" discriminator-value="student">
<!--className不能选定非空-->
<property name="className" column="className"/>
</subclass>
</class>
public class PeopleEntity {
public int id;
public String type;
public String peopleName;
...
}
public class StudentEntity extends PeopleEntity {
public String className;
...
}
查询操作:
// 类型不匹配 -> 返回null
StudentEntity studentEntity = session.get(StudentEntity.class, 3);
System.out.println(studentEntity.getClassName());
List<StudentEntity> studentEntityList = session.createQuery("from StudentEntity").list();
System.out.println(studentEntityList.size());
joined-subclass继承关系映射
joined-subclass标签,提供的功能是只能为子类设定外部表,而且没有鉴别器,即子类一张表,父类一张表,子类以父类的主键为外键。父类对应的表中,没有判断类型的列。
<class name="PeopleEntity" table="people" schema="test">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="peopleName" column="peopleName"/>
<!--创建student表额外存储student类的属性-->
<joined-subclass name="StudentEntity" table="student">
<!--PeopleEntity.id参照student表的student_id属性-->
<key column="student_id"/>
<property name="className" column="className"/>
</joined-subclass>
</class>
union-subclass继承关系参考
union-subclass是将父类中的属性,添加到子类对应的表中去了。包括父类中的外键。union-class和前两个的区别就在于外键的不同,前两个标签,如果子类有单独对应的表的话,这个表的外键是其父类中的主键,而使用union-class,子类对应的表中的外键则和父类的外键是一样的,因为子类把父类继承的属性,也加到了自己的表当中。这样子类和父类的地位就相当了。
<class name="PeopleEntity" table="PEOPLE" schema="test">
<id name="id" column="id"/>
<property name="peopleName" column="peopleName"/>
<!--创建student表额外存储student类的属性-->
<union-subclass name="StudentEntity" table="STUDENTS">
<property name="className" column="className"/>
</union-subclass>
</class>