Hibernate - 单向一对多关联关系映射

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/J080624/article/details/82999721

上篇博文描述了Hibernate - 单向多对一关联关系映射,本篇博文继续学习单向一对多关系映射。

这里Customer:Order= 1:N,外键保存在Order表中。

【1】修改Customer和Order

Customer修改如下:

public class Customer {

	private Integer customerId;
	private String customerName;
	
	private Set<Order> orders;
	
	//拥有属性orders
	public Set<Order> getOrders() {
		return orders;
	}
	
	public void setOrders(Set<Order> orders) {
		this.orders = orders;
	}

	public Integer getCustomerId() {
		return customerId;
	}

	public void setCustomerId(Integer customerId) {
		this.customerId = customerId;
	}

	public String getCustomerName() {
		return customerName;
	}

	public void setCustomerName(String customerName) {
		this.customerName = customerName;
	}

	@Override
	public String toString() {
		return "Customer [customerId=" + customerId + ", customerName=" + customerName + ", orders=" + orders + "]";
	}

}

Customer.hbm.xml修改如下:

<hibernate-mapping package="com.jane.model">
    
    <class name="Customer" table="CUSTOMERS">
    
        <id name="customerId" type="java.lang.Integer">
            <column name="CUSTOMER_ID" />
            <generator class="native" />
        </id>
    
        <property name="customerName" type="java.lang.String">
            <column name="CUSTOMER_NAME" default="null" />
        </property>
        <!--
         name="orders"表示一的一端拥有多的那端的属性;
         key节点中属性column="customer_id"表示外键(数据库多的一端拥有的)
		-->
        <set name="orders" table="ORDERS">
        	<key column="customer_id"></key>
        	<one-to-many class="Order"/>
        </set>
    </class>
</hibernate-mapping>

<key>元素设定本持久化类在Set对应表中的外键列名。如上值Customer类在ORDERS表中的外键列名–customer_id。

Order修改如下:

public class Order {
	
	private Integer orderId;
	private String orderName;

	public Integer getOrderId() {
		return orderId;
	}

	public void setOrderId(Integer orderId) {
		this.orderId = orderId;
	}

	public String getOrderName() {
		return orderName;
	}

	public void setOrderName(String orderName) {
		this.orderName = orderName;
	}

	@Override
	public String toString() {
		return "Order [orderId=" + orderId + ", orderName=" + orderName+"]";
	}
	
}

Order.hbm.xml如下:

<hibernate-mapping package="com.jane.model">

    <class name="Order" table="ORDERS">

        <id name="orderId" type="java.lang.Integer">
            <column name="ORDER_ID" />
            <generator class="native" />
        </id>
        
        <property name="orderName" type="java.lang.String">
            <column name="ORDER_NAME" default="null" />
        </property>
    </class>
</hibernate-mapping>

生成的数据库表结构如下所示:

//Customers表
CREATE TABLE `customers` (
  `CUSTOMER_ID` int(11) NOT NULL AUTO_INCREMENT,
  `CUSTOMER_NAME` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`CUSTOMER_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

//Orders表
CREATE TABLE `orders` (
  `ORDER_ID` int(11) NOT NULL AUTO_INCREMENT,
  `ORDER_NAME` varchar(255) DEFAULT NULL,
  `customer_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`ORDER_ID`),
  KEY `FK1nbewmmir6psft27yfvvmwpfg` (`customer_id`),
  CONSTRAINT `FK1nbewmmir6psft27yfvvmwpfg` FOREIGN KEY (`customer_id`) REFERENCES `customers` (`CUSTOMER_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

可以发现,无论是多对一还是一对多,外键都是多的一端数据表所持有。

单向多对一中,以多的一端为主,在多的一端xml中使用<many-to-one/>进行配置。
单向一对多中,以一的一端为主,在一的一端xml中使用<one-to-many/>进行配置。


【2】代码测试

① 单向一对多持久化

和单向多对一持久化不同的是,单向 1-n 关联关系执行保存时, 一定会多出 UPDATE 语句。因为 n 的一端在插入时不会同时插入外键列。

	@Test
	public void testOneToManySave(){
		Customer customer = new Customer();
		customer.setCustomerName("AAA");
		customer.setOrders(new HashSet<>());
		
		Order order1 = new Order();
		order1.setOrderName("O-JJ-1");
		
		Order order2 = new Order();
		order2.setOrderName("O-JJ-2");
		System.out.println(customer);
		
		//建立关联关系
		customer.getOrders().add(order1);
		customer.getOrders().add(order2);
		
		session.save(customer);
		session.save(order1);
		session.save(order2);
		
	}

测试结果如下:

Hibernate: 
    insert 
    into
        CUSTOMERS
        (CUSTOMER_NAME) 
    values
        (?)
Hibernate: 
    insert 
    into
        ORDERS
        (ORDER_NAME) 
    values
        (?)
Hibernate: 
    insert 
    into
        ORDERS
        (ORDER_NAME) 
    values
        (?)
Hibernate: 
    update
        ORDERS 
    set
        customer_id=? 
    where
        ORDER_ID=?
Hibernate: 
    update
        ORDERS 
    set
        customer_id=? 
    where
        ORDER_ID=?

② 单向一对多获取对象

默认对关联的多的一方使用懒加载的加载策略,只有在使用的时候才会进行查询。

测试代码如下:

	@Test
	public void testOneToManyGet(){
		Customer customer = session.get(Customer.class, 1);
		System.out.println(customer);
		
		System.out.println(customer.getOrders().size());
	}

测试结果如下:

Hibernate: 
    select
        customer0_.CUSTOMER_ID as CUSTOMER1_0_0_,
        customer0_.CUSTOMER_NAME as CUSTOMER2_0_0_ 
    from
        CUSTOMERS customer0_ 
    where
        customer0_.CUSTOMER_ID=?
Hibernate: 
    select
        orders0_.customer_id as customer3_2_0_,
        orders0_.ORDER_ID as ORDER_ID1_2_0_,
        orders0_.ORDER_ID as ORDER_ID1_2_1_,
        orders0_.ORDER_NAME as ORDER_NA2_2_1_ 
    from
        ORDERS orders0_ 
    where
        orders0_.customer_id=?
Customer [customerId=1, customerName=AAA, orders=[Order [orderId=1, orderName=O-JJ-1], Order [orderId=2, orderName=O-JJ-2]]]
2

③ 单向一对多更新操作

代码如下:

	@Test
	public void testUpdate(){
		Customer customer = session.get(Customer.class, 1);
		
		customer.getOrders().iterator().next().setOrderName("O-XXX-10");
	}

测试结果如下:

Hibernate: 
    select
        customer0_.CUSTOMER_ID as CUSTOMER1_0_0_,
        customer0_.CUSTOMER_NAME as CUSTOMER2_0_0_ 
    from
        CUSTOMERS customer0_ 
    where
        customer0_.CUSTOMER_ID=?
Hibernate: 
    select
        orders0_.customer_id as customer3_2_0_,
        orders0_.ORDER_ID as ORDER_ID1_2_0_,
        orders0_.ORDER_ID as ORDER_ID1_2_1_,
        orders0_.ORDER_NAME as ORDER_NA2_2_1_ 
    from
        ORDERS orders0_ 
    where
        orders0_.customer_id=?
Hibernate: 
    update
        ORDERS 
    set
        ORDER_NAME=? 
    where
        ORDER_ID=?

单独更新CustomerName如下:

	@Test
	public void testUpdate(){
		Customer customer = session.get(Customer.class, 1);
		customer.setCustomerName("CC");
		System.out.println(customer.getCustomerName());
		System.out.println(customer);
	}

测试结果如下:

Hibernate: 
    select
        customer0_.CUSTOMER_ID as CUSTOMER1_0_0_,
        customer0_.CUSTOMER_NAME as CUSTOMER2_0_0_ 
    from
        CUSTOMERS customer0_ 
    where
        customer0_.CUSTOMER_ID=?
CC
Hibernate: 
    select
        orders0_.customer_id as customer3_2_0_,
        orders0_.ORDER_ID as ORDER_ID1_2_0_,
        orders0_.ORDER_ID as ORDER_ID1_2_1_,
        orders0_.ORDER_NAME as ORDER_NA2_2_1_ 
    from
        ORDERS orders0_ 
    where
        orders0_.customer_id=?
Customer [customerId=1, customerName=CC, orders=[Order [orderId=1, orderName=O-XXX-10], Order [orderId=2, orderName=O-JJ-2]]]
Hibernate: 
    update
        CUSTOMERS 
    set
        CUSTOMER_NAME=? 
    where
        CUSTOMER_ID=?

④ 单向一对多删除操作

默认情况下, 若删除 1 的一端, 则会先把关联的 n 的一端的外键置空, 然后进行删除。

测试代码如下:

	@Test
	public void testOneToManyDel(){
		Customer customer = session.get(Customer.class,1);
		session.delete(customer);
	}

测试结果如下:

//先查询
Hibernate: 
    select
        customer0_.CUSTOMER_ID as CUSTOMER1_0_0_,
        customer0_.CUSTOMER_NAME as CUSTOMER2_0_0_ 
    from
        CUSTOMERS customer0_ 
    where
        customer0_.CUSTOMER_ID=?
//更新Order表的外键Customer_ID 为null
Hibernate: 
    update
        ORDERS 
    set
        customer_id=null 
    where
        customer_id=?
 //删除Customers
Hibernate: 
    delete 
    from
        CUSTOMERS 
    where
        CUSTOMER_ID=?

综上可知,只有在持久化操作和删除操作时,单向一对多和单向多对一有所不同,在查找和更新时没有什么区别。

博文是基于XML进行讲解,那么注解版的如何使用呢?

参考博文:注解版的单向一对多

猜你喜欢

转载自blog.csdn.net/J080624/article/details/82999721
今日推荐