Spring Data JPA实践与学习(九)

Etity 之间的关联关系

实体与实体之间的关联关系一共分为四种,分别为 OneToOne、OneToMany、ManyToOne 和 ManyToMany;而实体之间的关联关系又分为双向的和单向的。实体之间的关联关系是在 JPA 使用中最容易发生问题的地方。

@OneToOne 关联关系

@OneToOne 一般表示对象之间一对一的关联关系,它可以放在 field 上面,也可以放在 get/set 方法上面。其中 JPA 协议有规定,如果是配置双向关联,维护关联关系的是拥有外键的一方,而另一方必须配置 mappedBy;如果是单项关联,直接配置在拥有外键的一方即可。
举例:
user 表是用户的主信息,user_info 是用户的扩展信息,两者之间是一对一的关系。user_info 表里面有一个 user_id 作为关联关系的外键,如果是单项关联,我们的写法如下:

@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class User {
   @Id
   @GeneratedValue(strategy= GenerationType.AUTO)
   private Long id;
   private String name;
   private String email;
   private String sex;
   private String address;
}

User 实体里面什么都没变化,不需要添加 @OneToOne 注解。我们只需要在拥有外键的一方配置就可以,所以 UserInfo 的代码如下:

@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString(exclude = "user")
public class UserInfo {
   @Id
   @GeneratedValue(strategy= GenerationType.AUTO)
   private Long id;
   private Integer ages;
   private String telephone;
   @OneToOne //维护user的外键关联关系,配置一对一
   private User user;
}

上面试单项关联关系,那么双向关联应该怎么配置呢?我们保持 UserInfo 不变,在 User 实体对象里面添加这一段代码即可。

@OneToOne(mappedBy = "user")
private UserInfo userInfo;

@interface OneToOne 源码解读

public @interface OneToOne {
    //表示关系目标实体,默认该注解标识的返回值的类型的类。
    Class targetEntity() default void.class;
    //cascade 级联操作策略,就是我们常说的级联操作
    CascadeType[] cascade() default {};
    //数据获取方式EAGER(立即加载)/LAZY(延迟加载)
    FetchType fetch() default EAGER;
    //是否允许为空,默认是可选的,也就表示可以为空;
    boolean optional() default true;
    //关联关系被谁维护的一方对象里面的属性名字。 双向关联的时候必填
    String mappedBy() default "";
    //当被标识的字段发生删除或者置空操作之后,是否同步到关联关系的一方,即进行通过删除操作,默认flase,注意与CascadeType.REMOVE 级联删除的区别
    boolean orphanRemoval() default false;
}

mappedBy 注意事项

1、只有关联关系的维护方才能操作两个实体之间外键的关系。被维护方即使设置了维护方属性进行存储也不会更新外键关联。
2、mappedBy 不能与 @JoinColumn 或者 @JoinTable 同时使用,因为没有意义,关联关系不在这里面维护。
3、此外,mappedBy 的值是指另一方的实体里面属性的字段,而不是数据库字段,也不是实体的对象的名字。也就是维护关联关系的一方属性字段名称,或者加了 @JoinColumn / @JoinTable 注解的属性字段名称。如上面的 User 例子 user 里面 mappedBy 的值,就是 UserInfo 里面的 user 字段的名字。

CascadeType用法
在 CascadeType 的用法中,CascadeType 的枚举值只有五个,分别如下:

1、CascadeType.PERSIST 级联新建
2、CascadeType.REMOVE 级联删除
3、CascadeType.REFRESH 级联刷新
4、CascadeType.MERGE 级联更新
5、CascadeType.ALL 四项全选
JPA 2.0 还新增了 CascadeType.DETACH,即级联实体到 Detach 状态。

orphanRemoval 属性用法
orphanRemoval 表示当关联关系被删除的时候,是否应用级联删除,默认 false。

@ManyToOne& @OneToMany

@ManyToOne 代表多对一的关联关系,而 @OneToMany 代表一对多,一般两个成对使用表示双向关联关系。而 JPA 协议中也是明确规定:维护关联关系的是拥有外键的一方,而另一方必须配置 mappedBy。看下面的代码。

public @interface ManyToOne {
    Class targetEntity() default void.class;
    CascadeType[] cascade() default {};
    FetchType fetch() default EAGER;
    boolean optional() default true;
}
 public @interface OneToMany {
    Class targetEntity() default void.class;
 //cascade 级联操作策略:(CascadeType.PERSIST、CascadeType.REMOVE、CascadeType.REFRESH、CascadeType.MERGE、CascadeType.ALL)
如果不填,默认关系表不会产生任何影响。
    CascadeType[] cascade() default {};
//数据获取方式EAGER(立即加载)/LAZY(延迟加载)
    FetchType fetch() default LAZY;
    //关系被谁维护,单项的。注意:只有关系维护方才能操作两者的关系。
    String mappedBy() default "";
//是否级联删除。和CascadeType.REMOVE的效果一样。两种配置了一个就会自动级联删除
    boolean orphanRemoval() default false;
}

我们看到上面的字段和 @OneToOne 里面的基本一样,用法是一样的,不过需要注意以下几点:

@ManyToOne 一定是维护外键关系的一方,所以没有 mappedBy 字段;
@ManyToOne 删除的时候一定不能把 One 的一方删除了,所以也没有 orphanRemoval 的选项;
@ManyToOne 的 Lazy 效果和 @OneToOne 的一样,所以和上面的用法基本一致;
@OneToMany 的 Lazy 是有效果的。

@ManyToOne 的 lazy 机制和用法,与 @OneToOne 的一样,@ManyToOne 和 @OneToMany 的最佳实践,与 @OneToOne 的完全一样,也是尽量避免双向关联,一切级联更新和 orphanRemoval 都保持默认规则,并且 fetch 采用 lazy 延迟加载。

@ManyToMany

@ManyToMany 代表多对多的关联关系,这种关联关系任何一方都可以维护关联关系。当用到 @ManyToMany 的时候一定是三张表,不要想着建两张表,两张表肯定是违背表的设计原则的。

那么我们看下 @ManyToMany 的语法。

public @interface ManyToMany {
    Class targetEntity() default void.class;
    CascadeType[] cascade() default {};
    FetchType fetch() default LAZY;
    String mappedBy() default "";
}

基本上和其他的相同,@OneToMany 的最佳实践同样适用,一般是在中间表对象里面做单向关联,这样会让实体之间的关联关系简单很多。
与 @OneToMany 一样的道理,不要用级联删除和 orphanRemoval=true。
FetchType 采用默认方式:fetch = FetchType.LAZY 的方式。

学习参考自:拉勾教育

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值