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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Integer 转成Long类型数据

    Integer 转成Long类型数据Intege 的数据有一个 longValue 的函数 可以将其转换成 long 类型的数据代码如下 publicstatic Stringargs nbsp nbsp nbsp nbsp nbsp nbsp Integera 1 nbsp nbsp nbsp nbsp nbsp nbsp System out println a nbsp nbsp nbsp nbsp nbsp nbsp longb a longValue nbsp nbsp nbsp nbsp nbsp nbsp System out p

    2025年11月2日
    3
  • Java设计模式之结构型:桥接模式

    Java设计模式之结构型:桥接模式

    2021年10月5日
    43
  • qtcpsocket多线程_qtcpsocket接收数据

    qtcpsocket多线程_qtcpsocket接收数据简述最近在写有关网络传输的项目,使用了Qt封装的QTcpSocket,但是发现很多的跨线程导致死机的问题,也许是我了解的不够深入吧。最开始是自己继承一个线程然后把套接字传递到线程使用遇到程序崩溃;否决后使用了QObject::moveToThread()的方式,虽然程序可以正常发送接收数据但是对于QTcpSocket(moveToThread后属于子线程)与主线程的交互并不是很友好,还是存在一些问题;最后是考虑到了QTcpSocket跨线程崩溃说明它本身内置了一些发送或者接收的线程,这样…

    2025年10月14日
    3
  • 3.7v锂电池升压电路_锂电池升压5v电路图

    3.7v锂电池升压电路_锂电池升压5v电路图三节3.7V的锂电池串联,11.1V和最大12.6V锂电池充电电路的解决方案。在应用中,一般使用低压5V,如USB口直接输入的给三串锂电池充电,还有是15V或者18V,20V输入降压给锂电池充电的两种情况。PW4053是输入5V升压充电管理芯片,PW4203是输入15V-20V降压充电三节锂电池IC5V,USB口输入,给三节锂电池12.6V充电电路:PW4053是一款5V输入,最大1.2A充电电流,支持三节锂离子电池的升压充电管理IC。PW4053集成功率MOS…

    2022年9月26日
    2
  • 简介pid参数整定的基本方法_一阶倒立摆的PID

    简介pid参数整定的基本方法_一阶倒立摆的PID0.前言关于PID参数的整定,网上调节的口诀、原则、方法满天飞,但是并没有具体的到步的教程,作为初学者且非自动化相关专业学生有点看不懂、一脸懵逼,走了不少弯路,呕心沥血才调节好,之后才看得懂那些口诀、原则。为了让大家少走弯路,这里将给出圆周倒立摆直立环PID参数整定的具体步骤。多图预警!圆周倒立摆整体图1.PID编程及理解磨刀不误砍材工,是骡子是马,咱先看看,要想调好PI…

    2022年8月18日
    23
  • ureport 显示html,UReport2 与业务结合

    ureport 显示html,UReport2 与业务结合本小节中我们将介绍如何在业务页面中展示报表、导出报表文件、引用报表内容等操作。报表相关URL在配置好一个包含UReport2的项目后,就可以运行我们的项目,打开UReport2的基于网页的报表设计器,它的地址如下:UReport2报表设计器URLhttp://host[:port][/context-path]/ureport/designer如果我们是在本地启动项目,并且服务器端口号为8080,…

    2025年7月3日
    7

发表回复

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

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