Hibernate一对多和多对一

一、思考一对一与一对多的区别:

一对一 == 主表的主键对应外表的主键,两者根据主键来进行查询与删除
一对多 == 主表的主键对应外表的外键,类似于我们之前学习过的设置主外键关系

二、思考级联和关联关系区别?:

 级联

就是对一个对象进行操作的时候,会把他相关联的对象也一并进行相应的操作,相关联的对象意思是指 在一对多关系中,班级跟学生,Student的实体类中,存在着Classes对象的引用变量,如果保存Classes对象的引用变量有值的话,则该值就是相关联的对象,并且在对student进行save时,如果保存Classes对象的引用变量有值,那么就会将Classes对象也进行save操作, 这个就是级联的作用。并且在哪方设置级联,那么就保存那方的数据对应将跟她相关联的数据也一起保存

  cascade关系有以下几种

          all: 所有情况下均进行关联操作,即save-update和delete。
          none: 所有情况下均不进行关联操作。这是默认值。 
          save-update: 在执行save/update/saveOrUpdate时会将这个相关联的对象(前提是有这个对象,也就是引用对象变量有值)进行相应的操作,
          delete: 在执行delete 时进行关联操作。
          all-delete-orphan: 当一个节点在对象图中成为孤儿节点时,删除该节点,

 

孤儿节点:,举个例子,班级和学生,一张classes表,一张student表,student表中有5个学生的数据,其5个学生都属于这个班级,也就是这5个学生中的外键字段都指向那个班级,现在删除其中一个学生(remove),进行的数据操作仅仅是将student表中的该学生的外键字段置为null,也就是说,则个学生是没有班级的,所以称该学生为孤儿节点,我们本应该要将他完全删除的,但是结果并不如我们所想的那样,所以设置这个级联属性,就是为了删除这个孤儿节点。也就是解决这类情况。

关联关系:

单向关联:单向关联是指只有一方有另一方的关联信息而另一方没有关联信息,

双向关联:双向关联是指两方都有另一方的关联信息

当你对数据进行新增修改和删除,必须需要设置级联关系,

简单一点,我们可以理解成,关联关系就是主外键,级联就是设置了单向关系或者双向关系然后可以进行一系列的CURD的

三、inverse

值是boolean值,也就是能设置为true或false。 如果一方的映射文件中设置为true,说明在映射关系(一对多,多对多等)中让对方来维护关系。如果为false,就自己来维护关系。默认值是true。 并且这属性只能在一端设置。比如一对多,这个一端。也就是在有set集合的这方设置。

      维护关系:维护什么关系呢?包括两个方面

        1、也就是维护外键的关系了,通俗点讲,就是哪一方去设置这个被外键约束的字段的值。就拿上面这个例子来说,staff和dept两张表不管进行什么操作,只要关系到了另一张表,就不可避免的要通过操作外键字段,比如,staff查询自己所属的部门,就得通过被外键约束的字段值到dept中的主键中查找,如果dept想查询自己部门中有哪些员工,就拿着自己的主键值跟staff中的外键字段做比较,找到相同的值则是属于自己部门的员工。 这个是查询操作, 现在如果是添加操作呢,staff表中添加一条记录,并且部门属于dept表中的其中一个,staff中有被外键约束修饰的字段,那是通过staff的insert语句就对这个外键字段赋值,还是让dept对象使用update语句对其赋值呢,两个都能对这个外键字段的值进行操作,谁去操作呢?如果不做设置,两个都会操作,虽然不会出现问题,但是会影响性能,因为staff操作的话,在使用insert语句就能设置外键字段的值了,但是dept也会进行对其进行操作,又使用update语句,这样一来,这个update就显的很多余。

        2、维护级联的关系,也就是说如果如果让对方维护关系,则自己方的级联将会失效,对方设置的级联有用,如果自己维护关系,则自己方的级联会有用,但是对方设置的级联就会失效。

 

      就上面的运行结果,当我们在操作时,有一个insert和一个update分别取操作同一个数据, 这就证实了我们上面所说的观点,两个表度对其维护外键关系。 



Hibernate: 
    insert 
    into
        dept
        (name, id) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        staff
        (name, deptId, id) 
    values
        (?, ?, ?)
Hibernate: 
    update
        staff 
    set
        deptId=? 
    where
        id=?

     为了解决这种问题,使用inverse这个属性,来只让一方维护关系(维护外键值)。

在一的一方设置该属性,inverse=true 是默认值,也就是说让Tb_Nation来维护这种关系。

在主表中设置  <set name="sp" table="TB_PROVINCE" inverse="true" lazy="false" cascade="all-delete-orphan">
            <key>
                <column name="NID" />
            </key>
            <one-to-many class="com.zking.hibernate05_01.entity.Tb_Province" />
        </set>

因为改变的是主外键的编号,所以在列里面写的是主键

6.在从表中设置 

 <many-to-one  lazy="false" name="nation" class="com.zking.hibernate05_01.entity.Tb_Nation">
            <column name="nid" />
        </many-to-one>

四、lazy

class元素的lazy属性设定为true,表示延迟加载,如果lazy设为false,则表示立即加载。以下对这二点进行说明。
     立即加载:表示Hibernate在从数据库中取得数据组装好一个对象(如学生1)后, 会立即再从数据库取得数据组装此对象所关联的对象(如学生证1)。
     延迟加载:表示Hibernate在从数据库中取得数据组装好一个对象(如学生1)后,不会立即再从数据库中取得数据组装此对象所关联的对象(如学生1),而是等到需要时,才会从数据库取得数据组装此关联对象。

五、CURD

 

//直接新增,没有查询
	@Test
	public void add() {
	Session session=	SessionFactoryUtils.openSession();
	Tb_Nation n = new Tb_Nation();
		n.setNname("中国");
		Tb_Province p1 = new Tb_Province();
		p1.setPname("湖南");
		Tb_Province p2 = new Tb_Province();
		p2.setPname("湖北");
		Tb_City c1=new Tb_City();
		c1.setCname("长沙");
		Tb_City c2=new Tb_City();
		c2.setCname("衡阳");
		Tb_City c3=new Tb_City();
		c3.setCname("湖北1");	 
		//国家-》省区互设
		p1.setNation(n);
		p2.setNation(n);
		n.getSp().add(p1);
		n.getSp().add(p2);
		//省区-》城市互设
		p1.getSc().add(c1);
		p1.getSc().add(c2);
		p2.getSc().add(c3);
		c1.setProvince(p1);
		c2.setProvince(p1);
		c3.setProvince(p2);
		//提交数据到数据库
		session.save(n);
		session.beginTransaction().commit();
		SessionFactoryUtils.myclose();
		 
	}
@Test
	public void query() {
		Session session=SessionFactoryUtils.openSession();
		String id="01220f20-b4d2-11e8-83d3-208984958495";
		Tb_Nation n=session.get(Tb_Nation.class, id);
		System.out.println("Tb_Nation:"+n.getNname());
		Set<Tb_Province> sp=n.getSp();
		for(Tb_Province p:sp) {
			System.out.println("Tb_Province:"+p);
			Set<Tb_City> sc = p.getSc();
			for(Tb_City c:sc) {
				System.out.println("Tb_City:"+c);
			}
		}
		String str=JSON.toJSONString(n);
		System.out.println(str);
		session.beginTransaction().commit();
		SessionFactoryUtils.myclose();
	}
//先查询后修改
	@Test
	public void update() {
		Session session=SessionFactoryUtils.openSession();
		String id="cc3f9128-b4c4-11e8-ad58-208984958495";
		Tb_Nation n=session.get(Tb_Nation.class, id);
		n.setNname("中国中国");
		for(Tb_Province p:n.getSp()) {
			if(p.getPname().equals("湖南")) {
				p.setPname("湖南湖南");
			}
			for(Tb_City c:p.getSc()) {
				if(c.getCname().equals("长沙")) {
					c.setCname("长沙长沙");
				}
			}
		}
		session.update(n);
		session.beginTransaction().commit();
		SessionFactoryUtils.myclose();
	}
//先查询后删除(查询为按照关系查询从nation的一个对应数据到province对应的数据到city),先删从表再删主表
	@Test
	public void deleteAll() {
		Session session=SessionFactoryUtils.openSession();
		String id="cc3f9128-b4c4-11e8-ad58-208984958495";
		Tb_Nation n=session.get(Tb_Nation.class, id);
		session.delete(n);
		session.beginTransaction().commit();
		SessionFactoryUtils.myclose();
	}
//先根据删除的对象一个个往上级进行查询,每一个关系都查询一遍,最后查询到此对象进行删除
	//注意改成级联删除
	@Test
	public void deleteCity() {
		Session session=SessionFactoryUtils.openSession();
		String id="a93207fc-b4cd-11e8-ad58-208984958495";
		Tb_City c=session.get(Tb_City.class, id);
		session.delete(c);
		session.beginTransaction().commit();
		SessionFactoryUtils.myclose();
	}
//先往上一级查询,查询完后在望下一级查询,先找到此对象存在的下一级别,先删除从表,再删主表
	@Test
	public void deleteProvince() {
		Session session=SessionFactoryUtils.openSession();
		String id="a93311fb-b4cd-11e8-ad58-208984958495";
		Tb_Province p=session.get(Tb_Province.class, id);
		session.delete(p);
		session.beginTransaction().commit();
		SessionFactoryUtils.myclose();
	}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值