Hibernate框架–学习笔记(中):一对多配置、多对多配置

Hibernate框架–学习笔记(中):一对多配置、多对多配置

一、一对多:

一个客户可以有多个联系人,一个联系人只能属于一个客户。

1、一对多映射配置:

(1)创建实体类

//客户类:一个客户可以有多个联系人,一个联系人只能属于一个客户
public class Customer {

	private Integer cid;
	private String custName;
	private String custLevel;
	private String custSource;//客户来源
	private String custPhone;
	private String custMobile;
	
	//一个客户可以有多个联系人
	//hibernate要求使用集合表示多的数据,使用set集合
	private Set<LinkMan> setLinkMan=new HashSet<LinkMan>();
	
	public Set<LinkMan> getSetLinkMan() {
		return setLinkMan;
	}
	public void setSetLinkMan(Set<LinkMan> setLinkMan) {
		this.setLinkMan = setLinkMan;
	}
	public Integer getCid() {
		return cid;
	}
	public void setCid(Integer cid) {
		this.cid = cid;
	}
	public String getCustName() {
		return custName;
	}
	public void setCustName(String custName) {
		this.custName = custName;
	}
	public String getCustLevel() {
		return custLevel;
	}
	public void setCustLevel(String custLevel) {
		this.custLevel = custLevel;
	}
	public String getCustSource() {
		return custSource;
	}
	public void setCustSource(String custSource) {
		this.custSource = custSource;
	}
	public String getCustPhone() {
		return custPhone;
	}
	public void setCustPhone(String custPhone) {
		this.custPhone = custPhone;
	}
	public String getCustMobile() {
		return custMobile;
	}
	public void setCustMobile(String custMobile) {
		this.custMobile = custMobile;
	}
}
//联系人类:一个联系人只能属于一个客户
public class LinkMan {
	private Integer lkm_id;
	private String lkm_name;
	private String lkm_gender;//性别
	private String lkm_phone;
	
	//一个联系人只能属于一个客户
	private Customer customer;
	
	public Customer getCustomer() {
		return customer;
	}
	public void setCustomer(Customer customer) {
		this.customer = customer;
	}
	public Integer getLkm_id() {
		return lkm_id;
	}
	public void setLkm_id(Integer lkm_id) {
		this.lkm_id = lkm_id;
	}
	public String getLkm_name() {
		return lkm_name;
	}
	public void setLkm_name(String lkm_name) {
		this.lkm_name = lkm_name;
	}
	public String getLkm_gender() {
		return lkm_gender;
	}
	public void setLkm_gender(String lkm_gender) {
		this.lkm_gender = lkm_gender;
	}
	public String getLkm_phone() {
		return lkm_phone;
	}
	public void setLkm_phone(String lkm_phone) {
		this.lkm_phone = lkm_phone;
	}
}

(2)在xxx.hbm.xml配置文件进行配置:

Customer.hbm.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!-- 创建客户端的映射配置文件 -->
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>

	<class name="com.zwp.onetomany.Customer" table="t_customer">
	
		<id name="cid" column="cid">
			<generator class="native"></generator>
		</id>
		
		<property name="custName" column="custName"></property>
		<property name="custLevel" column="custLevel"></property>
		<property name="custSource" column="custSource"></property>
		<property name="custPhone" column="custPhone"></property>
		<property name="custMobile" column="custMobile"></property>
		
		<!-- 在客户映射文件中,表示所有联系人
			使用set标签表示所有的联系人,set标签里面有name属性
			name属性值写在客户实体类里面表示联系人的set集合名称-->
		<set name="setLinkMan">
			<!-- 一对多建表,有外键
				hibernate机制,双向维护外键,在一和多的哪一方都需要配置外键
				column属性值,外键名称-->
			<key column="clid"></key>
			<!-- 客户所有的联系人,class里面写联系人实体全路径 -->
			<one-to-many class="com.zwp.onetomany.LinkMan"/>
		</set>
	</class>
</hibernate-mapping>

LinkMan.hbm.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!-- 创建联系人的映射配置文件 -->
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>

	<class name="com.zwp.onetomany.LinkMan" table="t_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>
		
		<!--表示联系人所属客户
		name属性:因为在联系人实体类使用customer对象表示,写customer名称
		class属性:customer全路径
		column属性:外键名称 
		 -->
		<many-to-one name="customer" class="com.zwp.onetomany.Customer" column="clid"></many-to-one>
	</class>
	
</hibernate-mapping>

(3) 在核心配置文件hibernate.cfg.xml配置文件进行配置:

	<!-- 把映射文件放到核心配置文件中 -->
	<mapping resource="com/zwp/onetomany/Customer.hbm.xml" />
	<mapping resource="com/zwp/onetomany/LinkMan.hbm.xml" />

(4)测试代码:

//一对多测试类
public class OTMtest {
	//演示 OID查询,对象导航查询
	//OID查询:根据id查询,返回一个对象
	//对象导航查询:根据id查询客户,在根据这个客户查询所有的联系人
	@Test
	public void TextSelect1(){
		
		SessionFactory sessionfactory=null;
		Session session=null;
		Transaction tx=null;
		
		try{
			sessionfactory=HibernateUtil.getSessionFactory();
			session=sessionfactory.openSession();
			tx=session.beginTransaction();
			
			Customer customer=session.get(Customer.class, 1);
			Set<LinkMan> linkman=customer.getSetLinkMan();
			
			System.out.println(linkman.size());
			tx.commit();
		}catch(Exception e)
		{
			e.printStackTrace();
			tx.rollback();
		}
		finally{
			session.close();
			sessionfactory.close();
		}
	}
}

2、一对多级联操作:

(1)级联保存:

需求:添加客户,为这个客户添加一个联系人。

	//一对多级联保存
	@Test
	public void TestAdd(){
		SessionFactory sessionfactory=null;
		Session session=null;
		Transaction tx=null;
		
		try{
			sessionfactory=HibernateUtil.getSessionFactory();
			session=sessionfactory.openSession();
			tx=session.beginTransaction();
			
			//1、创建客户和联系人对象
			Customer customer=new Customer();
			customer.setCustLevel("vip");
			customer.setCustName("谷歌");
			customer.setCustMobile("1321515");
			customer.setCustPhone("1165666");
			customer.setCustSource("网络");
			
			LinkMan linkMan=new LinkMan();
			linkMan.setLkm_name("mike");
			linkMan.setLkm_gender("男");
			linkMan.setLkm_phone("1351565");
			
			//2、建立客户对象和联系人对象的关系
			customer.getSetLinkMan().add(linkMan);
			linkMan.setCustomer(customer);
			
			//3、保存到数据库中
			session.save(customer);
			session.save(linkMan);
			
			tx.commit();
		}catch(Exception e){
			e.printStackTrace();
			tx.rollback();
		}
		finally{
			session.close();
			sessionfactory.close();
		}
	}

以下是上边代码的简化写法:

第一步:在客户的映射文件Customer.hbm.xml中的set标签中配置cascade进行级联保存;

第二步:创建客户和联系人对象,只需要把联系人放到客户中,保存客户就可以了。

<!-- 在客户映射文件中,set标签表示所有的联系人
	    cascade="save-update,delete":级联保存,级联删除 -->
<set name="setLinkMan" cascade="save-update,delete">
	<key column="clid"></key>
	<!-- 客户所有的联系人,class里面写联系人实体全路径 -->
	<one-to-many class="com.zwp.onetomany.LinkMan"/>
</set>
    //一对多级联保存,简化方式
	@Test
	public void TestAdd(){
		SessionFactory sessionfactory=null;
		Session session=null;
		Transaction tx=null;
		
		try{
			sessionfactory=HibernateUtil.getSessionFactory();
			session=sessionfactory.openSession();
			tx=session.beginTransaction();
			
			//1、创建客户和联系人对象
			Customer customer=new Customer();
			customer.setCustLevel("vip");
			customer.setCustName("YY欢聚时代");
			customer.setCustMobile("1321515");
			customer.setCustPhone("1165666");
			customer.setCustSource("网络");
			
			LinkMan linkMan=new LinkMan();
			linkMan.setLkm_name("John");
			linkMan.setLkm_gender("男");
			linkMan.setLkm_phone("1351565");
			
			//2、建立客户对象和联系人对象的关系
			customer.getSetLinkMan().add(linkMan);
			//linkMan.setCustomer(customer);
			
			//3、保存到数据库中
			session.save(customer);
			//session.save(linkMan);
			
			tx.commit();
		}catch(Exception e){
			e.printStackTrace();
			tx.rollback();
		}
		finally{
			session.close();
			sessionfactory.close();
		}
	}

 

(2)级联删除:

第一步:在客户的映射文件Customer.hbm.xml中的set标签中配置cascade进行级联删除;

第二步:在代码中直接删除客户。

	//一对多级联删除
	@Test
	public void TestDel(){
		
		SessionFactory sessionfactory=null;
		Session session=null;
		Transaction tx=null;
		
		try{
			sessionfactory=HibernateUtil.getSessionFactory();
			session=sessionfactory.openSession();
			tx=session.beginTransaction();
			
			//1、根据id查询客户对象
			Customer customer = session.get(Customer.class, 4);
			//2、调用方法删除
			session.delete(customer);
			
			tx.commit();
		}catch(Exception e){
			e.printStackTrace();
			tx.rollback();
		}
		finally{
			session.close();
			sessionfactory.close();
		}
	}

(3)inverse属性:

①问题:hibernate是使用双向维护外键,会造成性能下降。

②解决方案:让其中一方放弃外键维护。在一对多里面,让一的那方放弃维护。

③在客户的映射文件Customer.hbm.xml中的set标签中配置inverse;

inverse属性默认值,false不放弃关系的维护,true 表示放弃关系维护。

<!-- 在客户映射文件中,表示所有联系人。
	inverse属性默认值,false不放弃关系的维护,true 表示放弃关系维护-->
<set name="setLinkMan" cascade="save-update,delete" inverse="true">
	<!-- 一对多建表,有外键
		hibernate机制,双向维护外键,在一和多的哪一方都需要配置外键
		column属性值,外键名称 -->
	<key column="clid"></key>
	<!-- 客户所有的联系人,class里面写联系人实体全路径 -->
	<one-to-many class="com.zwp.onetomany.LinkMan"/>
</set>

 

 

二、多对多:

1、多对多映射配置:

以用户和角色为例子

第一步:创建实体类,用户和角色:

第二步:让两个实体类之间互相表示:

①一个用户里面表示所有角色,使用set集合

②一个角色有多个用户,使用set集合

//用户实体类:一个用户有多个角色
public class User {
	private Integer user_id;
	private String user_name;
	private String user_passsword;
	
	//角色的set集合
	private Set<Role> setRole=new HashSet<Role>();
	
	public Set<Role> getSetRole() {
		return setRole;
	}
	public void setSetRole(Set<Role> setRole) {
		this.setRole = setRole;
	}
	public Integer getUser_id() {
		return user_id;
	}
	public void setUser_id(Integer user_id) {
		this.user_id = user_id;
	}
	public String getUser_name() {
		return user_name;
	}
	public void setUser_name(String user_name) {
		this.user_name = user_name;
	}
	public String getUser_passsword() {
		return user_passsword;
	}
	public void setUser_passsword(String user_passsword) {
		this.user_passsword = user_passsword;
	}
	
}
//角色实体类:一个角色有多个用户
public class Role {
	private Integer role_id;
	private String role_name;
	private String role_memo;//角色描述
	
	//用户的set集合
	private Set<User> setUser=new HashSet<User>();
	
	public Set<User> getSetUser() {
		return setUser;
	}
	public void setSetUser(Set<User> setUser) {
		this.setUser = setUser;
	}
	public Integer getRole_id() {
		return role_id;
	}
	public void setRole_id(Integer role_id) {
		this.role_id = role_id;
	}
	public String getRole_name() {
		return role_name;
	}
	public void setRole_name(String role_name) {
		this.role_name = role_name;
	}
	public String getRole_memo() {
		return role_memo;
	}
	public void setRole_memo(String role_memo) {
		this.role_memo = role_memo;
	}
}

第三步:配置映射关系:

①基本配置

②配置多对多关系

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 创建用户的映射配置文件User.hbm.xml -->
<hibernate-mapping>
	<class name="com.zwp.manytomany.User" table="t_user">
		<id name="user_id" column="user_id">
			<generator class="native"></generator>
		</id>
		<property name="user_name" column="user_name"></property>
		<property name="user_passsword" column="user_passsword"></property>
	
	<!-- 在用户里面表示所有角色,使用set标签;name属性:角色属性set集合名称;table:第三张表名称;	-->
	<set name="setRole" table="user_role">
		<!-- key标签里面配置,配置当前映射文件第三张表外键名称 -->
		<key column="userid"></key>
		<!-- class:角色实体类全路径;column:角色在第三张表外键名称 -->
		<many-to-many class="com.zwp.manytomany.Role" column="roleid"></many-to-many>
	</set>
	</class>
</hibernate-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 创建角色的映射配置文件Role.hbm.xml -->
<hibernate-mapping>
	<class name="com.zwp.manytomany.Role" table="t_role">
		<id name="role_id" column="role_id">
			<generator class="native"></generator>
		</id>
		<property name="role_name" column="role_name"></property>
		<property name="role_memo" column="role_memo"></property>
		
		<set name="setUser" table="user_role">
			<key column="roleid"></key>
			<many-to-many class="com.zwp.manytomany.User" column="userid"></many-to-many>
		</set>
	</class>
</hibernate-mapping>

第四步:在核心配置文件hibernate.cfg.xml中引入映射文件:

<!-- 把映射文件放到核心配置文件中 -->
<mapping resource="com/zwp/manytomany/Role.hbm.xml" />
<mapping resource="com/zwp/manytomany/User.hbm.xml" />

至此,hibernate多对多映射的配置已经完成。

 

2、多对多级联保存:

第一步:在用户的映射文件User.hbm.xml中的set标签中配置cascade进行级联保存;

第二步:创建用户和角色对象,只需要把角色放到用户中,保存用户就可以了。

	<set name="setRole" table="user_role" cascade="save-update">
		<!-- key标签里面配置,配置当前映射文件第三张表外键名称 -->
		<key column="userid"></key>
		<!-- class:角色实体类全路径;column:角色在第三张表外键名称 -->
		<many-to-many class="com.zwp.manytomany.Role" column="roleid"></many-to-many>
	</set>
	@Test
	public void Sava(){
		//多对多级联保存
		//<set name="setRole" table="user_role" cascade="save-update">
		SessionFactory sessionfactory = null;
		Session session = null;
		Transaction tx=null;
		
		try{
			sessionfactory=HibernateUtil.getSessionFactory();
			session=sessionfactory.openSession();
			
			tx=session.beginTransaction();
			
			//创建用户和角色
			User user1=new User();
			user1.setUser_name("小张");
			user1.setUser_passsword("213456");
			User user2=new User();
			user2.setUser_name("小王");
			user2.setUser_passsword("354656");
			
			Role role1=new Role();
			role1.setRole_name("总经理");
			role1.setRole_memo("总经理");
			Role role2=new Role();
			role2.setRole_name("秘书");
			role2.setRole_memo("秘书");
			Role role3=new Role();
			role3.setRole_name("保安");
			role3.setRole_memo("保安");
			
			user1.getSetRole().add(role1);
			user1.getSetRole().add(role2);
			
			user2.getSetRole().add(role2);
			user2.getSetRole().add(role3);
			
			session.save(user1);
			session.save(user2);
			
			tx.commit();
		}catch(Exception e){
			e.printStackTrace();
			tx.rollback();
		}
		finally{
			session.close();
			sessionfactory.close();
		}		
	}

 

3、多对多级联删除

在用户的映射文件User.hbm.xml中的set标签中配置cascade进行级联删除;

	<!-- 在用户里面表示所有角色,使用set标签;name属性:角色属性set集合名称;table:第三张表名称;	-->
	<set name="setRole" table="user_role" cascade="delete">
		<!-- key标签里面配置,配置当前映射文件第三张表外键名称 -->
		<key column="userid"></key>
		<!-- class:角色实体类全路径;column:角色在第三张表外键名称 -->
		<many-to-many class="com.zwp.manytomany.Role" column="roleid"></many-to-many>
	</set>
        @Test
	public void DelTest(){
		//多对多级联删除
		//<set name="setRole" table="user_role" cascade="delete">
		SessionFactory sessionfactory = null;
		Session session = null;
		Transaction tx=null;
		
		try{
			sessionfactory=HibernateUtil.getSessionFactory();
			session=sessionfactory.openSession();
			
			tx=session.beginTransaction();
			
			User user=session.get(User.class, 1);
			session.delete(user);
			
			tx.commit();
			
		}catch(Exception e){
			e.printStackTrace();
			tx.rollback();
		}
		finally{
			session.close();
			sessionfactory.close();
		}		
	}

 

4、维护第三张表关系:

用户和角色的多对多关系,维护关系通过第三张表维护。

(1)让某个用户有某个角色:

第一步:根据id查询用户和角色;

第二步:把角色放到用户里面:即,把角色对象放到用户set集合。

(2)让某个用户没有某个角色:

第一步:根据id查询用户和角色;

第二步:从用户里面把角色去掉:即,从set集合里面把角色移除。

	@Test
	public void TextTbable(){
		//多对多维护第三张表
		SessionFactory sessionfactory = null;
		Session session = null;
		Transaction tx=null;
		
		try{
			sessionfactory=HibernateUtil.getSessionFactory();
			session=sessionfactory.openSession();
			
			tx=session.beginTransaction();
			
			User user=session.get(User.class, 2);
			Role role=session.get(Role.class, 4);
			
			//让用户4拥有角色2:
			user.getSetRole().add(role);
			//让用户4失去角色2:
			user.getSetRole().remove(role);
			
			tx.commit();
		}catch(Exception e){
			e.printStackTrace();
			tx.rollback();
		}
		finally{
			session.close();
			sessionfactory.close();
		}		
	}

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/114722.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 三层交换机 ospf_三层交换机实验报告

    三层交换机 ospf_三层交换机实验报告03-三层交换机的OSPF实验

    2022年4月21日
    82
  • mysql版本查询命令「建议收藏」

    mysql版本查询命令「建议收藏」mysql版本查询命令有:1、输入“selectversion();”命令,按回车键,即可查看当前mysql版本;2、输入“status”命令,按回车键,即可查看当前mysql版本。在我们的电脑上打开mysql控制台,输入密码进去方法一:输入“selectversion();”命令,按回车键,可以看到mysql的版本号方法二:可以输入“status”命令,按回车键,看到mysql的版本号是8.0.28…

    2022年9月25日
    0
  • 6.25科技新闻4

    6.25科技新闻4Lytro光场相机体验评测Lytro光场相机是一款可以先拍照,后对焦的相机。当时一出现就引起挺大的反响的,现在就随小编一起来体验一下这款光场相机吧! 关于光场相机的外观,小编不再累述了。各位可以到之前的《先拍后对焦LYTRO光场相机图赏》里面观看完整外观图。 首先我们来看看官方介绍:小编大概把图中的意思翻译了一下,翻译都在图上,看

    2022年6月5日
    129
  • 8. 强化学习之——模仿学习

    8. 强化学习之——模仿学习课程大纲注:本文所有内容源自于B站周博磊老师更新完的强化学习纲要课程,听完之后获益很多,本文也是分享我的听课笔记。周老师Bilibili视频个人主页:https://space.bilibili.com/511221970?spm_id_from=333.788.b_765f7570696e666f.2感谢周老师:)…

    2022年9月18日
    0
  • Springboot自动装配原理_自动装配原理

    Springboot自动装配原理_自动装配原理springboot自动装配原理详解1)传统ssm整合redis的时候需要在xml的配置文件中进行大量的配置Bean我们在这里使用springboot来代替ssm的整合,只是通过xml的形式来整合redis第一步:加入配置<dependency><groupId>org.springframework.data</grou…

    2022年8月22日
    4
  • Jmeter面试题_软件测试的面试题及答案

    Jmeter面试题_软件测试的面试题及答案Jmter性能测试面试题

    2022年9月30日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号