Hibernate一对多/多对一关系映射详解及相应的增删查改操作

Hibernate 专栏收录该内容
3 篇文章 0 订阅

以客户与订单的关系为例

1.在实体模型类中绑定两者关系:
客户类:

public class Customer {
    private Integer id;//客户id
    private String name;//客户名称

    //一对多属性描述,一个客户有n个订单
    private Set<Order> orders = new HashSet<Order>();

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set<Order> getOrders() {
        return orders;
    }

    public void setOrders(Set<Order> orders) {
        this.orders = orders;
    }
}

订单类:

public class Order {
    private Integer id;//订单ID,工作中订单ID一般都UUID类型
    private String name;//订单名称

    private Customer customer;//订单只属性某个客户

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
    }
}

2.在映射文件中绑定两者关系:
客户类的映射文件Customer.hbm.xml:

<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.moli.hibernate.domain">
	<class name="Customer" table="t_customer">
		
		<id name="id">
			<generator class="native"/>
		</id>

		<!--模型和表的字段名一样,column可以不用写-->
		<property name="name"/>

		<!--描述一对多关系
			key中column写的是外键名称
			one-to-many:一对多,里面写class,写多的一方

			inverse:是hibernate双向关系中的基本概念。
					inverse的真正作用就是指定由哪一方来维护之间的关联关系。
					当一方中指定了“inverse=false”(默认),
					那么那一方就有责任负责关联关系。
			cascade:级联
					save-update:级联保存,级联修改. 保存A(客户)时,同时保存B(定单)
					delete:级联删除,删除A时,同时删除B.
					delete-orphan: 孤儿删除,解除关系,同时将B删除,A存在的。

					级联的组合
						如果需要配置多项,使用逗号分隔。<set cascade="save-update,delete">
						all : save-update 和 delete 整合
						all-delete-orphan = 【save-update,delete,delete-orphan】: 三个整合
		-->
		<set name="orders" inverse="true" cascade="all-delete-orphan">
			<key column="customer_id"></key>
			<one-to-many class="Order"></one-to-many>
		</set>
	</class>
</hibernate-mapping>

订单类的映射文件Order.hbm.xml:

<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.moli.hibernate.domain">
	<class name="Order" table="t_order">
		<id name="id">
			<generator class="native"/>
		</id>

		<property name="name" />


		<!--描述Customer的关系
			many-to-one:多对一
			class:写一的一方
			column:写外键
		-->
		<many-to-one name="customer" class="Customer" column="customer_id"/>
	</class>
</hibernate-mapping>

这样关系就映射好了,接下来做增删查改练习

package com.moli.hibernate.test;

import java.util.Date;
import java.util.Iterator;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
import com.moli.hibernate.domain.Customer;
import com.moli.hibernate.domain.Order;
import com.moli.hibernate.domain.User;

//一对多关系数据操作测试
public class YiDuiDuoTestClass {

	// 保存一对多/多对一的数据
	@Test
	public void test1() {

		// 获取核心 配置文件对象,默认是加载src下的hibernate.cfg.xm文件
		Configuration cfg = new Configuration().configure();

		// 创建会话工厂
		SessionFactory factory = cfg.buildSessionFactory();

		// 通过会话工厂创建会话【会话相当于连接Connect】
		Session session = factory.openSession();

		// 开启事务
		session.getTransaction().begin();

		// 创建客户对象
		Customer customer = new Customer();
		customer.setName("墨漓");

		// 创建两个订单
		Order order1 = new Order();
		order1.setName("内存条");

		Order order2 = new Order();
		order2.setName("主板");

		// 维护订单与客户关系
		order1.setCustomer(customer);
		order2.setCustomer(customer);

		// 维护客户与订单关系
		customer.getOrders().add(order1);
		customer.getOrders().add(order2);

		// 保存数据
		session.save(customer);// 保存完,客户有id
		session.save(order1);
		session.save(order2);

		// 提交事务
		session.getTransaction().commit();

		// 关闭会话
		session.close();

		// 关闭工厂,释放资源
		factory.close();

	}

	// 查询一对多/多对一的数据
	@Test
	public void test2() {

		// 获取核心 配置文件对象,默认是加载src下的hibernate.cfg.xm文件
		Configuration cfg = new Configuration().configure();

		// 创建会话工厂
		SessionFactory factory = cfg.buildSessionFactory();

		// 通过会话工厂创建会话【会话相当于连接Connect】
		Session session = factory.openSession();

		/**
		 * 默认情况,只有当使用Customer的orders的数据,会执行SQL查询
		 */
		// 1.查询ID为1的客户
		Customer customer = (Customer) session.get(Customer.class, 1);

		// 2.获取名字
		System.out.println("客户的名字:" + customer.getName());

		// 3.获取这个客户的所有定单

		Set<Order> orders = customer.getOrders();
		for (Order o : orders) {
			System.out.println("购买订单名称:" + o.getName());
		}

		// 关闭会话
		session.close();

		// 关闭工厂,释放资源
		factory.close();

	}

	// 普通删除一对多/多对一的数据
	@Test
	public void test3() {

		// 获取核心 配置文件对象,默认是加载src下的hibernate.cfg.xm文件
		Configuration cfg = new Configuration().configure();

		// 创建会话工厂
		SessionFactory factory = cfg.buildSessionFactory();

		// 通过会话工厂创建会话【会话相当于连接Connect】
		Session session = factory.openSession();

		// 开启事务
		session.getTransaction().begin();

		// 查询ID为1的客户
		Customer customer = (Customer) session.get(Customer.class, 1);

		// 如果要删除一对多,至少你要把order的约束去除
		for (Order order : customer.getOrders()) {
			// order.setCustomer(null);// 会执行update语句,把数据库的外键设置为null
			session.delete(order);// 先删除用户相应订单
		}

		// 删除客户
		session.delete(customer);

		// 提交事务
		session.getTransaction().commit();

		// 关闭会话
		session.close();

		// 关闭工厂,释放资源
		factory.close();

	}

	// 级联保存一对多/多对一的数据(需在映射文件中配置cascade级联属性)
	@Test
	public void test4() {

		// 获取核心 配置文件对象,默认是加载src下的hibernate.cfg.xm文件
		Configuration cfg = new Configuration().configure();

		// 创建会话工厂
		SessionFactory factory = cfg.buildSessionFactory();

		// 通过会话工厂创建会话【会话相当于连接Connect】
		Session session = factory.openSession();

		// 开启事务
		session.getTransaction().begin();

		// 创建客户对象
		Customer customer = new Customer();
		customer.setName("墨漓");

		// 创建两个订单
		Order order1 = new Order();
		order1.setName("内存条");

		Order order2 = new Order();
		order2.setName("主板");

		// 维护订单与客户关系
		order1.setCustomer(customer);
		order2.setCustomer(customer);

		// 维护客户与订单关系
		customer.getOrders().add(order1);
		customer.getOrders().add(order2);

		// 保存数据
		session.save(customer);// 只提交客户,会自动级联保存订单数据

		// 提交事务
		session.getTransaction().commit();

		// 关闭会话
		session.close();

		// 关闭工厂,释放资源
		factory.close();

	}

	// 级联删除一对多/多对一的数据(需在映射文件中配置cascade级联属性)
	// 删除A的同时删除B,实现原理:先删除B,再删除A
	@Test
	public void test5() {

		// 获取核心 配置文件对象,默认是加载src下的hibernate.cfg.xm文件
		Configuration cfg = new Configuration().configure();

		// 创建会话工厂
		SessionFactory factory = cfg.buildSessionFactory();

		// 通过会话工厂创建会话【会话相当于连接Connect】
		Session session = factory.openSession();

		// 开启事务
		session.getTransaction().begin();

		// 通过ID获取指定客户
		Customer customer = (Customer) session.get(Customer.class, 3);

		// 删除
		session.delete(customer);

		// 提交事务
		session.getTransaction().commit();

		// 关闭会话
		session.close();

		// 关闭工厂,释放资源
		factory.close();

	}

	// 级联孤儿删除一对多/多对一的数据(需在映射文件中配置cascade级联属性)
	// 孤儿删除,解除关系,同时将B删除,A仍然存在
	@Test
	public void test6() {

		// 获取核心 配置文件对象,默认是加载src下的hibernate.cfg.xm文件
		Configuration cfg = new Configuration().configure();

		// 创建会话工厂
		SessionFactory factory = cfg.buildSessionFactory();

		// 通过会话工厂创建会话【会话相当于连接Connect】
		Session session = factory.openSession();

		// 开启事务
		session.getTransaction().begin();

		// 通过ID获取指定客户
		Customer customer = (Customer) session.get(Customer.class, 5);

		// 孤儿删除(把客户里的所有定单移除)
		// 把订单从Customer的set集合删除
		Set<Order> orders = customer.getOrders();// 取出所有订单放入集合
		Iterator<Order> iterator = orders.iterator();// 迭代器
		while (iterator.hasNext()) {
			iterator.next();// 取出下一个元素
			iterator.remove();// 移除当前元素
		}

		// 提交事务
		session.getTransaction().commit();

		// 关闭会话
		session.close();

		// 关闭工厂,释放资源
		factory.close();

	}
}

  • 3
    点赞
  • 7
    评论
  • 2
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

评论 7 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:像素格子 设计师:CSDN官方博客 返回首页

打赏作者

_MoLi_

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值