• Hibernate制图(两)——许多-于─关系映射


      篇学习了Hibernate的基本映射,也就是单表映射,非常easy就能理解,可是对于关系数据库来说,表之间存在关系是比不可少的。关系数据库中存在的关系是通过主外键建立起来的。反应到Hibernate要怎样通过对象表现呢?以下我们就继续学习Hibernate的对象关系映射。

     

      我们先从最常见的多对一和一对多关系開始:


    多对一

      所谓多对一,在数据库中即在多的一端加入外键关联到一的一端,比方用户(User)和用户所在组(Group)的关系:一个User仅仅属于一个Group,一个Group有多个Group。而且能够通过User获取所在的Group

    通过以下的类图和表关系来看Hibernate的映射实现:


    1、首先是实体类UserGroup

    	package tgb.hibernate;
    	
    	/*
    	 * 用户组
    	 */
    	public class Group {
    	
    		private int id;		
    		private String name;
    	
    		public int getId() {
    			return id;
    		}	
    		public void setId(int id) {
    			this.id = id;
    		}
    	
    		public String getName() {
    			return name;
    		}	
    		public void setName(String name) {
    			this.name = name;
    		}
    	}
    	package tgb.hibernate;
    	
    	/**
    	 * 用户
    	 * @author Jones
    	 *
    	 */
    	public class User {
    	
    		private int id;		
    		private String name;
    		
    		//关联用户组属性(在用户实体中加入用户组。表明通过用户能够看到所在组)
    		private Group group;
    	
    		public int getId() {
    			return id;
    		}	
    		public void setId(int id) {
    			this.id = id;
    		}
    	
    		public String getName() {
    			return name;
    		}	
    		public void setName(String name) {
    			this.name = name;
    		}
    	
    		public Group getGroup() {
    			return group;
    		}	
    		public void setGroup(Group group) {
    			this.group = group;
    		}
    	}
    

    我们在多的一端(User)加入Group的属性引用,这样能够通过User对象得到Group对象。


    2、映射文件配置

    用户组Group.hbm.xml

    	<hibernate-mapping>
    		<class name="tgb.hibernate.Group" table="t_group">
    			<id name="id">
    				<generator class="native"/>
    			</id>
    			<property name="name"/>
    		</class>
    	</hibernate-mapping>
    

    用户User.hbm.xml

    	<hibernate-mapping>
    		<class name="tgb.hibernate.User" table="t_user">
    			<id name="id">
    				<generator class="native"/>
    			</id>
    			<property name="name"/>
    			<many-to-one name="group" column="groupid" cascade="save-update"/>
    		</class>
    	</hibernate-mapping>
    

    通过配置文件我们看到。多对一关系映射的实现是:

    在多的一端(User)採用例如以下标签映射:

    <many-to-onename="group" column="groupid"/>

      映射成功后。兴许就是对对象的操作(增删改查-持久化到数据库),用了以上映射,我们能够通过Hibernate的级联操作对实体进行快捷操作。可是这样还不够。这里就来看级联操作的问题。比如我们须要加入用户组和组下的用户:

    级联问题:

    session = HibernateUtils.getSession();
    session.beginTransaction();
    			
    Group group = new Group();
    group.setName("系统管理员");
    			
    User user1 = new User();
    user1.setName("张三");
    user1.setGroup(group);
    			
    User user2 = new User();
    user2.setName("李四");
    user2.setGroup(group);
    			
    session.save(user1);
    session.save(user2);
    
    //在清理缓存是错误发生TransientObjectException
    //由于Group为Transient状态。没有被session,在数据库中没有匹配的数据
    //而User为Persistent状态。在清理缓存时hibernate在缓存中无法找到Group对象
    //结论:Persistent状态的对象不能引用Transient状态的对象
    session.getTransaction().commit();

      正如凝视所说会发生TransientObjectException错误,在保存对象(user)过程中,该对象有一个属性(外键)关联的另外一个未持久化的对象(未保存的对象group),解决方法是先保存"被关联"的那个对象,才干保存先前的那个对象,当然我们这样能够实现我们的须要,可是Hibernate提供了更快捷的方式。以下看Hibernate的级联操作和配置。



    级联操作

      级联是对象之间的连锁操作,它仅仅影响加入、删除和改动。Hibernate对级联的控制是在配置文件的关系标签中通过cascade进行配置。

    还以加入用户组和用户为例,我们须要对<many-to-one>中加入:

    <many-to-one name="group" column="groupid" cascade="save-update"/>

    “cascade”就来说明在操作两个或多个关联对象,当对当中一个对象进行某种操作时,是否对其关联的对象也作类似的操作。比方我们保存用户是是否也同一时候保存其所在组。

    级联(Cascade)还有例如以下经常使用属性:

        (1)none:在保存。删除或改动当前对象时,不正确其附属对象(关联对象)进行级联操作。它是默认值。
        (2)save-update:在保存,更新当前对象时,级联保存,更新附属对象(暂时对象,游离对象)。
        (3)delete:在删除当前对象时,级联删除附属对象。
        (4)all:全部情况下均进行级联操作。即包括save-update和delete等等操作。
        (5)delete-orphan:删除此对象的同一时候删除与当前对象解除关系的孤儿对象(只使用于一对多关联关系中)。

        这些我们能够依据详细的业务进行设置。


    总结

       Hibernate中的关系映射反应的就是类之间的关系,关系数据库中就是主外键关系。数据库和UML我们都非常熟了,映射也就没有问题,当然关系映射在Hibernate是最基础的内容了。项目实践是不可缺少了。下文继续Hibernate的一对多映射(包含双向映射)。



    版权声明:本文博客原创文章。博客,未经同意,不得转载。

  • 相关阅读:
    谈一谈对象池SafeObjectPool能干什么
    .net core 程序退出事件
    .NETCore 快速开发做一个简易商城
    Git创建子分支,合并分支并提交
    Vue项目中关闭eslint的方法
    Missing space before function parentheses
    单引号变双引号 格式化去掉分号
    Docker Swarm搭建多服务器下Docker集群
    Asp.Net Core中服务的生命周期选项区别和用法
    KnockoutJS-模板绑定
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4675700.html
Copyright © 2020-2023  润新知