关系维护方和被维护方的理解关系维护方就是hibernate会主动去修改维护的,比如one1设置为关系维护方,one2为被维护方,那么在one1.save时,会主动修改one2,但是当one2save时就不会去管one1,除非你设置one2.save(one1),

当多的一方满足1、关系维护方和2、设置了级联属性。那么在做save操作前,只需要对多的一方做设置(如order.setUser(user))就可以了,不需要一的一方做设置(即不需要user.setOrders())。所以如果是一的一方做save操作时,必须两方都做设置(order.setUser(user)和user.setOrders())。因为在注解中,一的一方不能满足它是关系维护方这个条件。

所以我们将一的一方是设置级联,多的一方不设置级联,但设置为关系维护方是不合理的,我们可以将多的一方也设置级联,但如果将多的一方的cascade 设为 CascadeType.ALL,那么如果删除多的一方,会将一的一方也删除,所以设为 cascade = {CascadeType.PERSIST,CascadeType.REFRESH}即可。

所以如果你要person删除所有,那么设置person为ALL,而order设置为PERSIST,这就可以实现人没了,订单也没了,删除订单不会删除人。
---------------------

原文:https://blog.csdn.net/u011302734/article/details/76868090


mappedBy的理解:

声明于关系的被维护方,声明的值为关系的维护方的关系对象属性名。
在实例中,mappedBy被声明于person类中,其值为Order类中的Set对象"person"。即,Order为关系维护方,person为被维护方。

 

级联的理解级联的定义是一方操作会影响另一方。比如one1和one2进行级联,在one1设置级联cascade,那么在修改one1的时候也会修改one2,比如删除one1,设置cascade为ALL,就会删除one2。

@OneToOne(cascade =CascadeType.ALL)
private One2 one2;

 

Cascade的几种级联操作

指定cascade = CascadeType.PERSIST在实体类关联的实体字段上,那么保存该实体类时会级联保存该实体类关联的实体。即可以在添加one1保存时可以级联保存one2;

 

cascade = CascadeType.All,执行所有操作,包含PERSIST,即可以在添加one1保存时可以级联保存one2,级联删除时也可以删除one1,并且顺带删除one2;

 

cascade = CascadeType.REMOVE,级联删除,但是必须one1和one2在数据库中都有,才可以级联删除,测试的时候,你要new one1,还要new one2,然后保存one1,one2到数据库才可以进行级联删除。

 

cascade = CascadeType.MERGE CascadeType.MERGE
Cascade merge operation,级联更新(合并)操作。
当one中的数据改变,会相应地更新Course中的数据。

 

CascadeType.DETACH
Cascade detach operation,级联脱管/游离操作。
如果你要删除一个实体,但是它有外键无法删除,你就需要这个级联权限了。它会撤销所有相关的外键关联。

 

Cascade refresh operation,级联刷新操作。
假设场景 有一个订单,订单里面关联了许多商品,这个订单可以被很多人操作,那么这个时候A对此订单和关联的商品进行了修改,与此同时,B也进行了相同的操作,但是B先一步比A保存了数据,那么当A保存数据的时候,就需要先刷新订单信息及关联的商品信息后,再将订单及商品保存。(来自“汪三”的简书)

加载的理解

1、FetchType.LAZY:懒加载,加载一个实体时,定义懒加载的属性不会马上从数据库中加载。 2、FetchType.EAGER:急加载,加载一个实体时,定义急加载的属性会立即从数据库中加载。 3、比方User类有两个属性,name跟address,就像百度知道,登录后用户名是需要显示出来的,此属性用到的几率极大,要马上到数据库查,用急加载; 而用户地址大多数情况下不需要显示出来,只有在查看用户资料是才需要显示,需要用了才查数据库,用懒加载就好了。所以,并不是一登录就把用户 的所有资料都加载到对象中,于是有了这两种加载模式。

多的一方默认使用饥饿加载,一的一方默认使用懒加载。当多的一方使用delete时,没有级联操作时,即使是维护方(维护方一定要指定)也能做删除操作。但是如果此时一的一方使用饥饿加载,那么多的一方使用delete时会报错:org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations)。

那怎么办?解除要删除对象的多对一关系,两方都要设置,因为此时一的一方已经加载了多的一方,做法比如(order.getTblUser().getTblOrders().remove(order);
order.setTblUser(null);)。本来我以为维护方只要设置order.setTblUser(null)即可。但因为session缓存中一的一方已经有了它所对应的所有多的一方,此时它不能被删。

---------------------
原文:https://blog.csdn.net/u010082453/article/details/43339031

OPTIONAL的理解:

如果为true,在你数据库插入的时候,就不可以为空

 

一对多关系与多对一关系
  • 一对多关系即数据库中的一行数据关联另一个数据库中的多行关系。多对一与之相反。
  • 一对多与多对一关系也可能会有中间表关联两者。但是我们一般不建议使用中间表。使用mapperBy可以避免系统生成中间表(会在多的一方数据库中增加一个字段记录外键)。
  • 这两个关系中的mappedBy一般声明于一的一方,即一的一方为被维护方。
  • 当使用单向关联时,由父类管理关联关系,子类无法管理,而这时,父亲知道自己的儿子,但是,从儿子对象不知道父亲是谁。
    单向关联时,只指定<one-to-many>
    当使用双向关联时,关联关系的管理可以通过inverse指定,这时,儿子能清楚的知道自己的父亲是谁。 双向关联时,还要指定<many-to-one>
     
     
    多对多关系
    是关系数据库中两个表之间的一种关系, 该关系中第一个表中的一个行可以与第二个表中的一个或多个行相关。第二个表中的一个行也可以与第一个表中的一个或多个行相关。
    如果我们通过学生与课程的关系来说明多对多关系:一位学生,会修多门课程;而一门课程,也会被多位学生修习。此时,双方的关系即为多对多关系。
    拥有多对多关系的两个实体将会有一个中间表来记录两者之间的关联关系。
    当两个类(a,b)使用@ManyToMany注解时,会产生一个中间表a_b,该中间表表示两个类的关联关系,此时有两种情况:只有一端(类)维护该关联关系,两端(类)均可维护该关联关系。比如News和Label,一个News新闻可以有多个属性Label,一个Label下可以有多个属性,所以需要多对多
     
    仅News端可维护该关联关系,则意为只能通过向News类对象的集合属性labels中添加Label类的对象来更改中间表,即维护关联关系。
    在labels中设置Set<News>集合上设置(mappedBy=“**”),**是News的属性。比如在New上设置,private Set News,然后在labels上设置mappedBy=“labels” private Set<News> news = new HashSet<News>();说明这个labels被news维护,你看声明在Label类里面嘛,但是**是在News里嘛。所以呢,是被News维护啦,这是我方便记啦。
     
    若两边都维护需要设置@JoinTable,就是设置中间表了
    @JoinTable(name = "new_label", joinColumns = { @JoinColumn(name = "newsId", referencedColumnName = "newId") }, inverseJoinColumns = { @JoinColumn(name = "labelId", referencedColumnName = "labelId") })
    多对多中,joinColumns写的都是本表在中间表的外键名称, inverseJoinColumns写的是另一个表在中间表的外键名称。
    @JoinTable的属性:https://blog.csdn.net/jiangyu1013/article/details/79503581
    属性referencedColumnName标注的是所关联表中的字段名,若不指定则使用的所关联表的主键字段名作为外键
     
 targetEntity的理解:用于指定关联的类 @ManyToMany(targetEntity = **.class)
 
 @Onetoone,@Onetomany,@Many-to-one ,@ManytoMany加一个就相当于加一个关系,一个类中加,就是单向,两个类加,就是双向。

这是@Onetoone

package edu.zut.cs.zutnlp.platform.dao;

import edu.zut.cs.zutnlp.platform.base.domain.BaseEntity;

import javax.persistence.*;

@Table(name = "ONE1")
@Entity
public class One1 extends BaseEntity {

    @Column(name = "NAME")
    private String name;

    @OneToOne(cascade =CascadeType.ALL)//看这里看这里!!!!!!!!!!!!
package edu.zut.cs.zutnlp.platform.dao;

import edu.zut.cs.zutnlp.platform.base.domain.BaseEntity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;

@Table
@Entity
public class One2 extends BaseEntity {//这里的BaseEntity是我写的抽象层代码,里面也就是序列化了一下,还有个baseDao,baseDao就配置了一下Jpa接口。

    @Column(name = "NAME")
    private String name;

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public String getName() {

        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Column(name = "Age")
    private String age;
}

package edu.zut.cs.zutnlp.platform.dao;

import edu.zut.cs.zutnlp.platform.base.dao.GenericDaoTestCase;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

public class One1DaoTest extends GenericDaoTestCase<Long, One1,One1Dao> {//

    @Autowired
    One1Dao one1Dao;

    @Autowired
    One2Dao one2Dao;

    public void setOne2Dao(One2Dao one2Dao) {
        this.one2Dao = one2Dao;
    }

    public void setOne1Dao(One1Dao one1Dao) {
        this.one1Dao = one1Dao;
        this.dao=this.one1Dao;
    }

    @Test
    public void set(){
        One1 one1=new One1();
//        one1.setName("2");
//        One2 one2=new One2();
//        one2.setName("2de");
//        one2.setAge("15");
//        one1.setOne2(one2);
        one1=this.one1Dao.findByOne1_name("1");
        this.one1Dao.delete(one1);
        System.out.println("删除成功");
    }
}

 

!!!!!!!我删除了one1,就可以删除了one2,保存,更新,都可以
    private One2 one2;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public One2 getOne2() {
        return one2;
    }

    public void setOne2(One2 one2) {
        this.one2 = one2;
    }
}

此博文只是作为笔者学习记录之用,如有冒犯还请联系我

posted on 2018-11-12 21:30  纯正肉包  阅读(642)  评论(0编辑  收藏  举报