JPA 关系映射(OneToOne、OneToMany、ManyToMany)(IBM官方文档)

单向 OneToOne

单向一对一是关联关系映射中最简单的一种,简单地说就是可以从关联的一方去查询另一方,却不能反向查询

  • @OneToOne注解只用于关系的发出端,同时定义一个接收端类型的字段属性;
  • 单向的一对一关系在数据库中是以外键的形式被映射的,
  • 其中关系的发出端存储一个指向关系的接收端的一个外键
  • 缺省情况下这个外键的字段名称,是以它指向的表的名称加下划线“_”加“ID”组成的。
  • 当然我们也可以根据我们的喜好来修改这个字段,修改的办法就是使用 @JoinColumn 这个注解

@OneToOne注解

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OneToOne {
    Class targetEntity() default void.class;
    CascadeType[] cascade() default {};
    FetchType fetch() default FetchType.EAGER;
    boolean optional() default true;
    String mappedBy() default "";
    boolean orphanRemoval() default false;
}

# targetEntity属性表示默认关联的实体类型,默认为当前标注的实体类;
# cascade属性表示与此实体一对一关联的实体的联级样式类型。联级样式上当对实体进行操作时的策略。
说明:在定义关系时经常会涉及是否定义Cascade(级联处理)属性,担心造成负面影响.

  • ·不定义,则对关系表不会产生任何影响
  • ·CascadeType.PERSIST (级联新建)
  • ·CascadeType.REMOVE (级联删除)
  • ·CascadeType.REFRESH (级联刷新)
  • ·CascadeType.MERGE (级联更新)中选择一个或多个。
  • ·还有一个选择是使用CascadeType.ALL ,表示选择全部四项

# fetch属性是该实体的加载方式,有两种:LAZY和EAGER。
# optional属性表示关联的实体是否能够存在null值。默认为true,表示可以存在null值。如果为false,则要同时配合使用@JoinColumn标记。
# mappedBy属性用于双向关联实体时,标注在不保存关系的实体中。
在四种关联关系

关联指定列(@JoinColumn)

# @JoinColumn用于注释表中的字段,与@Column不同的是它要保存表与表之间关系的字段;
# name属性是用来标记表中对应的字段的名称。
如果不设置name的值,默认情况下,name的取值规则如下:name=关联的表的名称 + "_" + 关联表主键的字段名
# 默认情况下,关联的实体的主键一般用来做外键的。如果不想用主键作为外键,则需要设置referencedColumnName属性,
如: @JoinColumn(name="address_id", referencedColumnName="ref_id")
# @JoinColumn可以与@OneToOne、@ManyToOne或@ManyToMany标记同时使用。

双向 OneToOne

  • 双向关系有一方为关系的发出端,另一方是关系的反端,也就是“Inverse”端(接收端)。
  • @OneToOne注解,发出端和接收端都要使用,同时定义一个接收端类型的字段属性;
  • 同时@OneToOne注解中的“mappedBy”属性,这个在双向关系的“Inverse”端是必需的

单向 OneToMany

单向关系的一对多

  • @OneToMany 注解只用于关系的发出端(即“一”的一方),
  • 同时关系的发出端--定义一个集合类型的接收端的字段属性
  • 在一对多关联关系映射中,默认是以中间表的方式来映射这种关系的。
  • 中间表的名称为关系的拥有端和 Inverse 端中间用下划线连接。
  • 中间表的字两个字段分别为两张表的得表名加下划线“_”加 ID 组成。
  • 当然我们也可以改表这种默认的中间表的映射方式,我们可以在关系的拥有端使用 @JoinClolum 来使用外键的方式映射这个关系。

示例

假设有两个表,订单表和产品表,订单跟产品的关系是一对多的关系,那么在JPA中怎样表示一对多的关系呢?实体关系一对多映射有两种方式:

外键关联

//订单表

@Entity
@Table(name = "orders")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @OneToMany(cascade = {CascadeType.ALL})
    @JoinColumn(name = "order_id")
    private List<Product> productList;
...
}

//产品表

@Entity
@Table(name = "product")
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
...

这样在表product中会增加一列order_id

表关联【默认方式】

//订单表

@Entity
@Table(name = "orders")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @OneToMany(cascade = {CascadeType.ALL})
    @JoinTable(name = "order_has_product", joinColumns = {@JoinColumn(name = "order_id", referencedColumnName = "id")},inverseJoinColumns = {@JoinColumn(name = "product_id", referencedColumnName = "id")})
    private List<Product> productList;
...
}

joinColumns指定中间表中关联自己ID的字段,inverseJoinColumns表示中间表中关联对方ID的字段
这样在product表中不会增加任何外键,而是新建了一张order_has_product表

双向 OneToMany

双向一对多关系

  • @OneToMany(mappedBy='发出端实体名称小写') 注解用于关系的发出端(即“一”的一方),
  • 同时关系的发出端--定义一个集合类型的接收端的字段属性,
  • @ManyToOne注解用于关系的接收端端(即“多”的一方),
  • 同时关系的接收端--定义一个发出端的字段属性,

单向 ManyToMany

  • 多对多关联关系中只能通过中间表的方式进行映射。
  • @ManyToMany 注解用于关系的发出端
  • 同时关系的发出端--定义一个集合类型的接收端的字段属性;
  • 关系的接收端,不需要做任何定义;

双向 ManyToMany

  • @ManyToMany 注解用于关系的发出端和接收端
  • 同时关系的发出端和接收端--定义一个集合类型的接收端的字段属性;
  • 关系的接收端,@ManyToMany(mappedBy='集合类型发出端实体的字段名称');

 

参考来源:https://www.ibm.com/developerworks/cn/java/j-lo-jparelated/#icomments


————————————————
版权声明:本文为CSDN博主「琦彦」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/fly910905/article/details/79465859

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值