关联关系
什么是关联?
关联指的是类之间的引用关系。如果类A与类B关联, 那么被引用的类B将被定义为类A的属性。
为什么提到关联
所谓的一对多其实就是一个类当中将另一个类作为属性来使用。我们常见的一对多联系就是一个订单当中有多个订单项,而订单项也是一个有属性的类,且其是会定义为为订单的属性。
关联的分类
关联分为一对一、一对多、多对多、多对一、注意关联是有方向的。
一对多简单示例
我这边使用订单与订单项的关联关系来进行简单的示例,首先订单的实体类:
package com.zengjing.entity;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
public class Order implements Serializable{
private Integer orderId;
private String orderNo;
//默认不用去初始化订单项
private boolean initOrderItems=false;
/*关联指的是类之间的引用关系。如果类Order与类OrderItem关联,
那么被引用的类OrderItem将被定义为类Order的属性。:*/
private Set<OrderItem>orderItems=new HashSet<>();
public Set<OrderItem> getOrderItems() {
return orderItems;
}
public void setOrderItems(Set<OrderItem> orderItems) {
this.orderItems = orderItems;
}
public Order() {
super();
}
public Integer getOrderId() {
return orderId;
}
public void setOrderId(Integer orderId) {
this.orderId = orderId;
}
public String getOrderNo() {
return orderNo;
}
public void setOrderNo(String orderNo) {
this.orderNo = orderNo;
}
public Order(Integer orderId, String orderNo) {
super();
this.orderId = orderId;
this.orderNo = orderNo;
}
@Override
public String toString() {
return "Order [orderId=" + orderId + ", orderNo=" + orderNo + "]";
}
public boolean isInitOrderItems() {
return initOrderItems;
}
public void setInitOrderItems(boolean initOrderItems) {
this.initOrderItems = initOrderItems;
}
}
OrderItem订单项的实体类:
package com.zengjing.entity;
import java.io.Serializable;
/**
* 可以看做多对一
*/
public class OrderItem implements Serializable{
private Integer orderItemId;
private Integer productId;
private Integer quantity;
private Integer oid;
private Order order;
/*关联指的是类之间的引用关系。如果类OrderItem与类order关联,
那么被引用的类order将被定义为类OrderItem的属性。:*/
public OrderItem() {}
public Integer getOrderItemId() {
return orderItemId;
}
public void setOrderItemId(Integer orderItemId) {
this.orderItemId = orderItemId;
}
public Integer getProductId() {
return productId;
}
public void setProductId(Integer productId) {
this.productId = productId;
}
public Integer getQuantity() {
return quantity;
}
public void setQuantity(Integer quantity) {
this.quantity = quantity;
}
public Integer getOid() {
return oid;
}
public void setOid(Integer oid) {
this.oid = oid;
}
public OrderItem(Integer orderItemId, Integer productId, Integer quantity, Integer oid) {
super();
this.orderItemId = orderItemId;
this.productId = productId;
this.quantity = quantity;
this.oid = oid;
}
@Override
public String toString() {
return "OrderItem [orderItemId=" + orderItemId + ", productId=" + productId + ", quantity=" + quantity
+ ", oid=" + oid + "]";
}
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
}
配置实体类映射文件之Order.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 实体类映射文件 -->
<hibernate-mapping>
<class name="com.zengjing.entity.Order" table="t_order">
<id name="orderId" type="java.lang.Integer" column="order_id">
<generator class="increment"></generator>
</id>
<!-- 与实体类相匹配 -->
<property name="orderNo" type="java.lang.String" column="order_no"/>
<!-- 建立订单到订单项的一对多关联关系
1. lazy:默认值为true,true延迟加载,false立即加载(一般设置为true,不使用立即加载,因为影响查询性能)
2. outter-join:默认值为false,true使用左外联接查询关联的(但一般不用,因为当我们把该属性设置为true时,所有的查询语句都会默认左外联,那样性能不高)
3. inverse:默认值为false,true表示将对方设置为主控方(一对多双向关联中一般将多方设置为主控方,这样可以减少SQL语句的数量,减少多余的操作)
4. cascade:用来控制如何操作关联的持久化对象的(级联删除更新)
1. none:保存,更新或删除当前对象时,忽略其它关联的对象(注意:如果建立了关联关系,则不能使用此属性,报错:对象引用未保存的临时实例-保存临时实例)
2. save-update:保存、更新时级联保存所有的临时对象,并且级联更新关联的游离对象
3. delete:通过session的delete方法删除当前对象,级联删除关联的对象
4. all:等于save-update操作+delete操作
注:级联删除不建议使用(cascade:delete)
-->
<!--set标签name:多的一方的对象集合的属性名称-->
<set name="orderItems" inverse="true" cascade="save-update,delete" >
<!--key标签 column:多的一方的外键的名称 -->
<key column="oid"></key>
<!-- 从one到many的方向:操作one对象能同时操作many对象, class:多的一方的类的全路径 -->
<one-to-many class="com.zengjing.entity.OrderItem"></one-to-many>
</set>
</class>
</hibernate-mapping>
配置实体类映射文件之OrderItem.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 实体类映射文件 -->
<hibernate-mapping>
<class name="com.zengjing.entity.OrderItem" table="t_order_item">
<id name="orderItemId" type="java.lang.Integer" column="order_item_id">
<generator class="increment"></generator>
</id>
<!-- 与实体类相匹配 -->
<property name="productId" type="java.lang.Integer" column="product_id"/>
<property name="quantity" type="java.lang.Integer" column="quantity"/>
<!--1.注释 2.只读-->
<property name="oid" type="java.lang.Integer" column="oid" insert="false" update="false" />
<!-- 多对一关联关系 放置的是一方的对象 -->
<!--
name :一方的对象的属性名称
class :一方的类的全路劲
column :在多方的表的外键的名称
-->
<!-- 从many到one的方向:操作many对象能同时操作one对象 -->
<many-to-one name="order" class="com.zengjing.entity.Order" column="oid"/>
</class>
</hibernate-mapping>
注意要将实体类配置到核心文件当中!
其dao方法Junit测试:
package com.zengjing.dao;
import com.zengjing.entity.Order;
import com.zengjing.entity.OrderItem;
import junit.framework.TestCase;
public class OrderDaoTest extends TestCase {
Order order=null;
OrderItem orderItem=null;
OrderDao orderDao=new OrderDao();
protected void setUp() throws Exception {
order=new Order();
}
//增加订单
public void testAddOrder() {
order.setOrderNo("p20200729939");
for (int i = 0; i < 3; i++) {
orderItem=new OrderItem();
orderItem.setProductId(i+1);
orderItem.setQuantity(i+2);
orderItem.setOrder(order);
order.getItems().add(orderItem);
}
orderDao.addOrder(order);
}
}
结果:
关联的订单项: