Hibernate之一对多关联映射

目录

表关系分析

 一对多

 多对多

一对一

一对多关联映射

数据库表

cst_customer表(一)

cst_linkman表(多)  --lkm_cust_id

两表关系 

 实体类

Customer

Linkman

实体与表映射文件

Customer-cst_customer

Linkman-cst_linkman

Hibernate主配置文件

测试类

级联优化

cascade属性(简化操作,少写代码)

inverse属性(优化性能,提高关系维护)

 


表关系分析

Hibernate框架实现了ORM的思想,将关系数据库中表的数据映射成对象,使开发人员把对数据库的操作转化成对对象的操作,Hibernate的关联映射主要包括多表的映射配置、数据的增加、删除等。

数据库中多表之间存在着三种关系,也就是系统设计中的三种实体,在数据库中,实体表之间的关系映射是采用外键来描述的,如下图所示

  •  一对多

建表原则:在多的一方创建外键指向一的一方主键

  •  多对多

建表原则:创建一个中间表,中间表中至少两个字段作为外键分别指向多对多双方的主键

  • 一对一

建表原则

1)唯一外键对应,假设一对一中的任意一方为多,在多的一方创建外键指向一的一方主键,然后将外键设置为唯一

2)主键对应,一方的主键作为另一方的主键

 数据库表能够描述的实体数据之间的关系,通过对象也可以进行描述,所谓的关联映射就是将关联关系映射到数据库里,在对象模型中就是一个或多个引用。在Hibernate中采用Java对象关系来描述数据表之间的关系,具体图如下:

一对多关联映射

  • 数据库表

cst_customer表(一)

cst_linkman表(多)  --lkm_cust_id

两表关系 

  •  实体类

Customer

package com.mark.domain;

import java.util.HashSet;
import java.util.Set;

public class Customer {

	private Long cust_id;
	private String cust_name;
	private Long cust_user_id;
	private Long cust_create_id;
	private String cust_source;
	private String cust_industry;
	private String cust_level;
	private String cust_linkman;
	private String cust_phone;
	private String cust_mobile;
	
	//set集合存放多个Linkman对象
	private Set<Linkman> linkmans = new HashSet<Linkman>();
	
    //get|set方法省略...
	
}

Linkman

package com.mark.domain;

public class Linkman {
	private Long lkm_id;
	private String lkm_name;
	private Character lkm_gender;
	private String lkm_phone;
	private String lkm_mobile;
	private String lkm_email;
	private String lkm_qq;
	private String lkm_position;
	private String lkm_memo;
	
	//存放一个客户对象
	private Customer customer;
	
    //get|set方法省略....
}
  • 实体与表映射文件

Customer-cst_customer

核心配置

<!-- 配置多的一方关联对象 -->
                <!-- set标签:* name属性:多的一方集合的属性名称 -->
           <set name="linkmans">
                 <!-- key标签: * column属性:多的一方外键名称 -->
                 <key column="lkm_cust_id"></key>
                 <!-- one-to-many标签:* name属性:多的一方类全路径-->
                 <one-to-many class="com.mark.domain.Linkman"/>
            </set>

<?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 package="com.mark.domain">
	<class name="Customer" table="cst_customer">
	
		<!-- 实体与主键映射 -->
		<id name="cust_id" column="cust_id">
		  	<!-- 主键生成策略 -->
		  	<generator class="native"></generator>
		</id>
		
		<!-- 实体与表普通列映射 -->
		<property name="cust_name" column="cust_name"></property>
		<property name="cust_user_id" column="cust_user_id"></property>
		<property name="cust_create_id" column="cust_create_id"></property>
		<property name="cust_source" column="cust_source"></property>
		<property name="cust_industry" column="cust_industry"></property>
		<property name="cust_level" column="cust_level"></property>
		<property name="cust_linkman" column="cust_linkman"></property>
		<property name="cust_phone" column="cust_phone"></property>
		<property name="cust_mobile" column="cust_mobile"></property>
		
		<!-- 配置多的一方关联对象 -->
			<!-- set标签:
				   * name属性:多的一方集合的属性名称 -->
		<set name="linkmans">
			<!-- key标签:
				   * column属性:多的一方外键名称 -->
			<key column="lkm_cust_id"></key>
			<!-- one-to-many标签:
				   * name属性:多的一方类全路径
                             -->
			<one-to-many class="com.mark.domain.Linkman"/>
		</set>
	</class>
</hibernate-mapping>

Linkman-cst_linkman

核心配置

 <!-- 配置一的一方关联对象 -->
            <!-- many-to-one标签:
                   * name属性        :一的一方对象名
                   * class属性     :一的一方类全路径
                   * column属性  :外键名称
                   -->
            <many-to-one name="customer" class="com.mark.domain.Customer" column="lkm_cust_id"/>

<?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 package="com.mark.domain">
	<class name="Linkman" table="cst_linkman">
	
		<!-- 实体与主键映射 -->
		<id name="lkm_id" column="lkm_id">
		  	<!-- 主键生成策略 -->
		  	<generator class="native"></generator>
		</id>
		
		<!-- 实体与表普通列映射 -->
		<property name="lkm_name" column="lkm_name"></property>
		<property name="lkm_gender" column="lkm_gender"></property>
		<property name="lkm_phone" column="lkm_phone"></property>
		<property name="lkm_mobile" column="lkm_mobile"></property>
		<property name="lkm_email" column="lkm_email"></property>
		<property name="lkm_qq" column="lkm_qq"></property>
		<property name="lkm_position" column="lkm_position"></property>
		<property name="lkm_memo" column="lkm_memo"></property>
		
		<!-- 配置一的一方关联对象 -->
			<!-- many-to-one标签:
				   * name属性        :一的一方对象名
				   * class属性     :一的一方类全路径
				   * column属性  :外键名称
				   -->
			<many-to-one name="customer" class="com.mark.domain.Customer" column="lkm_cust_id"></many-to-one>
	</class>
</hibernate-mapping>
  • Hibernate主配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
	<!-- Hibernate核心文件配置 -->
<hibernate-configuration>
	<session-factory>
		<!-- 5个必要数据连接配置 -->
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql:///crm</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">root</property>
			<!--Hibernate方言 -->
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		
		<!-- 3个可选数据库操作配置 -->
			<!--Hibernate显示SQL语句  -->
		<property name="hibernate.show_sql">true</property>
			<!--Hibernate格式化SQL语句  -->
		<property name="hibernate.format_sql">true</property>
		<property name="hibernate.hbm2ddl.auto">update</property>
		
		<!--Hibernate加载映射  -->
		<mapping resource="com/mark/domain/Customer.hbm.xml"/>
		<mapping resource="com/mark/domain/Linkman.hbm.xml"/>
	</session-factory>
</hibernate-configuration>
  • 测试类

public class OneToMany {
	@Test
	public void test(){
		//获取Session对象
		Session session = HibernateUtil.openSession();
		//获取事务对象
		Transaction trans = session.beginTransaction();
		
		/*Customer customer = new Customer(); //一
		customer.setCust_name("菲尔米诺");*/
		
		Customer customer = session.get(Customer.class, 11L);
		Linkman man1 = new Linkman(); //多
		man1.setLkm_name("kitty");
		Linkman man2 = new Linkman(); //多
		man2.setLkm_name("milly");
		
		man1.setCustomer(customer);
		man2.setCustomer(customer);
		
		customer.getLinkmans().add(man1);
		customer.getLinkmans().add(man2);
		
		//将上述创建的瞬时对象转换成持久态对象
		session.save(customer);
		session.save(man1);
		session.save(man2);
		
		//开始事务
		trans.commit();
		//关闭session
		session.close();
	}
}

  • 级联优化

 级联是有方向性的,所谓的方向性是指,在保存一的一方级联多的一方和在保存多的一方级联一的一方

cascade属性(简化操作,少写代码)

一的一方和多的一方,两者二选一在set标签中加入cascade属性就可以实现级联操作

   <!-- set标签:
                   * name属性        :多的一方集合的属性名称
                   * cascade属性     :save-update(级联保存更新)、delete(级联删除)、all(前两者之和)-->

inverse属性(优化性能,提高关系维护)

因为双向维护外键关系,而且持久态对象可以自动更新数据库,更新客户的时候会修改一次外键,更新联系人的时候同样也会修改一次外键,这样就会产生了多余的SQL

为了去除冗余的SQL,只需要将一方的外键维护权即可,也就是说关系不是双方维护了,只需要交给某一方去维护就可以了。通常我们都是交给多的一方去维护,因为多的一方才是维护关系的最好地方,例如

一个老师对应多个学生,一个学生对应一个老师,这是典型的一对多。那么一个老师如果要记住所有学生的名字很难,但是如果让每个学生记住老师的名字就会很简单,所以在一对多种,一的一方都会放弃外键的维护权(关系维护)

这个时候,如果想让一的一方放弃外键的维护权,只需要进行如下配置

   <!-- set标签:
                   * name属性        :多的一方集合的属性名称
                   * inverse属性     : true(放弃)、false(默认,不放弃)--> 

猜你喜欢

转载自blog.csdn.net/mmake1994/article/details/81536571