Hibernate笔记 5:实体关联关系

来自Wikioe
Eijux讨论 | 贡献2022年6月19日 (日) 15:43的版本 (创建页面,内容为“category:Hibernate == 关于 == 数据库中多表之间存在着三种关联关系(一对一、一对多、多对多),用于描述实体数据之间的关系,而这种关系也可以通过对象进行描述。 实体关系 # 一对一: #: <syntaxhighlight lang="Java" highlight=""> class A{ B b; } class B{ A a; } </syntaxhighlight> #* 开发中并不常用; # '''一对多''': #: <syntaxhighlight lang="Java" highlight=""> class A{ Se…”)
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳到导航 跳到搜索


关于

数据库中多表之间存在着三种关联关系(一对一、一对多、多对多),用于描述实体数据之间的关系,而这种关系也可以通过对象进行描述。

实体关系

  1. 一对一:
    class A{
    	B b
    }
    
    class B{
    	A a
    }
    
    • 开发中并不常用;
  2. 一对多
    class A{
    	Set<B> bs;
    }
    
    class B{
    	A a
    }
    
  3. 多对多
    class A{
    	Set<B> bs;
    }
    
    class B{
    	Set<A> as;
    }
    

一对多

“一对多”关系分为“一端”与“多端”。

以下,讨论一对一关系。
以“客户”(Customer)与“联系人”(LinkMan)为例:
1、一个客户可以有多个联系人;
2、一个联系人只能被指定给一个客户;

实体类:

  1. Customer:
    public class Customer { 
    	private Long cust_id; 
    	private String cust_name;
    	private String cust_industry;
    	private String cust_level;
    	private String cust_phone; 
    
    	// 客户类中维护联系人对象集合
    	private Set<LinkMan> linkMans = new HashSet<LinkMan>(); 
    
    	// getter、setter
    	...
    }
    
  2. LinkMan:
    public class LinkMan { 
    	private Long lkm_id;
    	private String 1km_name;
    	private String lkm_phone;
    
    	// 联系人类中维护客户对象
    	private Customer customer; 
    
    	// getter、setter
    	...
    }
    

非级联操作(复杂写法)


创建映射:

  1. Customer.hbm.xml:
    ...
    <hibernate-mapping>
    	<class name="cn.itcast.hibernate.domain.Customer" table="cst_customer">
    		<id name= "cust_id"> 
    			<generator class="native"/> 
    		</id>
    		
    		<property name="cust_name" length="32"/> 
    		<property name="cust_industry" column= "cust_industry"/> 
    		<property name="cust_level" column= "cust_level"/> 
    		<property name="cust_phone" column= "cust_phone"/>
    		
    		<!-- 配置关联对象集合 -->
    		<set name="linkMans">
    			<key column="lkm_cust_id"></key>
    			<one-to-many class= "cn.itcast.hibernate.domain.LinkMan"/>
    		</set>
    	</class>
    </hibernate-mapping>
    
  2. LinkMan.hbm.xml:
    ...
    <hibernate-mapping>
    	<class name="cn.itcast.hibernate.domain.LinkMan" table="cst_linkMan">
    		<id name= "lkm_id"> 
    			<generator class="native"/> 
    		</id>
    		
    		<property name="1km_name" length="32"/> 
    		<property name="1km_name" column= "1km_name"/> 
    		<property name="lkm_phone" column= "lkm_phone"/> 
    		
    		<!-- 配置关联对象 -->
    		<many-to-one name="customer" class="cn.itcast.hibernate.domain.Customer" column="lkm_cust_id"/> 
    	</class>
    </hibernate-mapping>
    
  • 注意:“lkm_cust_id”为“cst_linkMan”表的外键(参照于“cst_customer”表)。【下同】
  • 注意:需要加载两个映射文件到核心配置文件。

测试代码:

	@Test 
	// 保存:一个客户和他的两个联系人
	public void demol() { 
		Session session = HibernateUtils.openSession(); 
		Transaction tx = session.beginTransaction(); 

		// 创建客户
		Customer customer = new Customer(); 
		customer.setCust_name("中国移动"); 

		// 创建联系人
		LinkMan linkManl = new LinkMan(); 
		linkManl.setLkm_name("老张"); 
		
		LinkMan linkMan2 = new LinkMan(); 
		linkMan2.setLkm_name("老李");
		
		// 建立关联关系
		customer.getLinkMans().add(linkManl);
		customer.getLinkMans().add(linkMan2);
		
		linkManl.setCustomer(customer); 
		linkMan2.setCustomer(customer); 

		// 保存
		session.save(customer); 
		session.save(linkManl); 
		session.save(linkManl); 

		tx.commit();
	}

如上代码,建立的关系是双向的:

  1. 建立关联时:Customer 对象关联了 LinkMan 对象,同时 LinkMan 对象也关联了 Customer 对象;
  2. 保存对象时:对 Customer 对象进行了保存,也分别对 LinkMan 对象进行了保存;

从控制台打印出的 SQL 语句可以看出:

  1. 执行了三次 insert(对 customer、linkManl、linkMan2)
  2. 执行了两次 update(对 linkManl、linkMan2 更新外键)
Hibernate:
	insert
	into
		cst_customer
		(cust_name, cust_industry, cust_level, cust_phone)
	values
		(?, ?, ?, ?)
Hibernate:
	insert
	into
		cst_linkMan
		(1km_name, lkm_phone, lkm_cust_id)
	values
		(?, ?, ?, ?)
Hibernate:
	insert
	into
		cst_linkMan
		(1km_name, lkm_phone, lkm_cust_id)
	values
		(?, ?, ?, ?)
Hibernate:
	update
		cst_linkMan
	set
		lkm_cust_id
	where
		lkm_id=?
Hibernate:
	update
		cst_linkMan
	set
		lkm_cust_id
	where
		lkm_id=?
非级联操作,是一种复杂的写法,在于


级联操作(cascade)


为什么需要级联?

级联保存

级联删除

外键维护(inverse)


为什么需要外键维护?

多对多