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();
		}		
	}

 

 

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

发表回复

您的电子邮箱地址不会被公开。

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