@OneToMany、@ManyToOne以及@ManyToMany讲解(五)

Wesley13
• 阅读 637

一、一对多(@OneToMany)
1、单向一对多模型
假设通过一个客户实体可以获得多个地址信息。
对于一对多的实体关系而言,表结构有两种设计策略,分别是外键关联和表关联。
(1) 映射策略---外键关联
在数据库中表customer和表结构address定义,如下:

create table customer (
  id int(20) not null auto_increment,
  name varchar(100),
  primary key(id)
)

create table address (
  id int(20) not null auto_increment,
  province varchar(50),
  city varchar(50),
  postcode varchar(50),
  detail varchar(50),
  customer_id int(20),
  primary key (id)
)

注意此时外键定义在多的一方,也就是address表中。

此时,表customer映射为实体CustomerEO,代码如下:

@Entity
@Table(name="customer")
public class CustomerEO implements java.io.Serializable {
  @OneToMany(cascade={ CascadeType.ALL })
  @JoinColumn(name="customer_id")
  private Collection<AddressEO> addresses = new ArrayList<AddressEO>();
 ...
}

注释@OneToMany的定义代码如下:

@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface OneToMany {
  Class targetEntity() default void.class;
  CascadeType[] cascade() default {};
  FetchType fetch() default LAZY;
  String mappedBy() default "";
}

使用时要注意一下几点问题:
a、targetEntity属性表示默认关联的实体类型。如果集合类中指定了具体类型了,不需要使用targetEntity.否则要指定targetEntity=AddressEO.class。
b、mappedBy属性用于标记当实体之间是双向时使用。

(2) 映射策略---表关联
在上面address表中去掉customer_id字段,在增加一个表ref_customer_address,如下:

--客户地址关系表
create table ref_customer_address (
  customer_id int(20) not null,
  address_id int(20) not null unique
)

此时表customer映射为CustomerEO实体,代码如下:

@Entity
@Table(name = "customer")
public class CustomerEO implements java.io.Serializable {
  ...
  @OneToMany(cascade = { CascadeType.ALL })
  @JoinTable(name="ref_customer_address",
           joinColumns={ @JoinColumn(name="customer_id",referencedColumnName="id")},
           inverseJoinColumns={@JoinColumn(name="address_id",referencedColumnName="id")})
  private Collection<AddressEO> addresses = new ArrayList<AddressEO>();
  ...
}

表关联@JoinTable,定义如下:

@Target({METHOD,FIELD}) 
public @interface JoinTable {
  String name() default "";
  String catalog() default "";
  String schema() default "";
  JoinColumn[] joinColumns() default {};
  JoinColumn[] inverseJoinColumns() default {};
  UniqueConstraint[] uniqueConstraints default {};
}

其中:
a、该标记和@Table相似,用于标注用于关联的表。
b、name属性为连接两张表的表名。默认的表名为:“表名1”+“-”+“表名2”,上面例子默认的表名为customer_address。
c、joinColumns属性表示,在保存关系中的表中,所保存关联的外键字段。
d、inverseJoinColumns属性与joinColumns属性类似,不过它保存的是保存关系的另一个外键字段。

(3) 默认关联
在数据库底层为两张表添加约束,如下:

create table customer_address (
  customer_id int(20) not null,
  address_id int(20) not null unique
)
alter table customer_address add constraint fk_ref_customer foreign key (customer_id) references customer (id);

alter table customer_address add constraint fk_ref_address foreign key (address_id) references address (id);

这样,在CustomerEO中只需要在标注@OneToMany即可!

二、多对一@ManyToOne
1、单向多对一模型。
(1) 外键关联
配置AddressEO实体如下:

@Entity
@Table(name="address")
public class AddressEO implements java.io.Serializable {
    
  @ManyToOne(cascade = { CascadeType.ALL })
  @JoinColumn(name="customer_id")
  private CustomerEO customer;
    
  // ...
}

@ManyToOne定义如下:

@Target({METHOD,FIELD}) @Retention(RUNTIME)
public @interface ManyToOne {
  Class targetEntity() default void.class;
  CascadeType[] cascade() default {};
  FetchType fatch() default EAGER;
  boolean optional() default true;
}

(2) 默认关联
数据库脚本定义的相关字段的约束,创建外键后,直接使用@ManyToOne

三、高级一对多和多对一映射
即双向关联模型,确定了双向关联后,多的一方AddressEO不变使用@ManyToOne,而CustomerEO实体修改为:

@Entity
@Table(name="customer")
public class CustomerEO {
    
  @OneToMany(mappedBy="customer")
  private Collection<AddressEO> addresses = new ArrayList<AddressEO>();
    
  // ...
}

其中,@OneToMany标记中的mappedBy属性的值为AddressEO实体中所引用的CustomerEO实体的属性名。

四、多对多(@ManyToMany)
和一对多类型,不在赘述。@ManyToMany标记的定义如下:

@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface ManyToMany {
  Class targetEntity() default void.class;
  CascadeType[] cascade() default {};
  FetchType fecth() default LAZY;
  String mappedBy() default "";
}

五、最后,谈谈关于集合类的选择
在映射关系中可以使用的集合类有Collection、Set、List和Map,下面看下如何选择。
1、定义时使用接口,初始化使用具体的类。
如Collection可以初始化为ArrayList或HashSet;
Set可以初始化为HashSet;
List可以初始化为ArrayList;
Map可以初始化为HashMap.
2、集合类的选择
Collection类是Set和List的父类,在未确定使用Set或List时可使用;
Set集合中对象不能重复,并且是无序的;
List集合中的对象可以有重复,并且可以有排序;
Map集合是带有key和value值的集合。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Stella981 Stella981
3年前
Go 语言编程 — gorm 的数据完整性约束
目录文章目录目录实体完整性(主键约束)用户定义完整性(非空约束、唯一约束、检查约束和默认值)参照完整性(外键约束)关联关系一对一、一对多关联多对多关联示例实体完整性(主键约束)每个关系(表)至少存在一个主
Stella981 Stella981
3年前
Django之ORM(多对多)
一、ManyToManyField1、classRelatedManager"关联管理器"是在一对多或者多对多的关联上下文中使用的管理器。它存在于下面两种情况:1.外键关系的反向查询2.多对多关联关系简单来说就是当 点后面的对象 可能存在多个的时
Stella981 Stella981
3年前
Hibernate利用关联关系操纵对象
Hibernate利用关联关系操纵对象数据对象之间关联关系有一对一、一对多及多对多关联关系。在数据库操作中,数据对象之间的关联关系使用JDBC处理很困难。本节讲解如何在Hibernate中处理这些对象之间的关联关系。本节使用到4个类,它们分别是Student(学生)、Card(学生证)、Group(班级)和Cou
Stella981 Stella981
3年前
Django框架(七):模型(三) 关联、模型类的属性
1\.关联1.1模型类关系关系型数据库的关系包括三种类型:ForeignKey:一对多,将字段定义在多的一端中。ManyToManyField:多对多,将字段定义在任意一端中。OneToOneField:一对一,将字段定义在任意一端中。1.1.1一对多关系
Wesley13 Wesley13
3年前
3 OneToMany ManyToMany MappedBy Cascade
1双向1N关联对于1N关联,Hibernate推荐使用双向关联,而且不要让1的一方控制关联关系,而使用多的一方控制关联关系。a.一的一方 表示班级@Entity@Table(name"team_1")publicclassTeam{@Id@Gen
Stella981 Stella981
3年前
Hibernate 单向的一对多关联映射
单向的一对多关联关系(OnetoMany)对象模型关系分析:少的一端:会通过引用一个多端的集合对象,建立对象模型关系多的一端:没有任何变化,不知道和少的一端存在着关系。关系模型分析:少的一端:没有任何变化多的一端:会和少的一端建立外键关系使用时需要少的一端所对应的XXX.hbm.xml中进行配置<bagname"对多的
Wesley13 Wesley13
3年前
ThinkPHP 根据关联数据查询 hasWhere 的使用实例
很多时候,模型关联后需要根据关联的模型做查询。场景:广告表(ad),广告类型表(ad\_type),现在需要筛选出广告类型表中id字段为1且广告表中status为1的列表先看关联的设置部分 publicfunctionadType(){return$thisbelongsTo('A
Stella981 Stella981
3年前
Django 关联对象操作及多表查询
关联表的数据操作一对多正向:如果这个模型有外键字段,通过这个模型外键进行操作叫正向!(https://img2018.cnblogs.com/blog/1633684/201905/163368420190507170738352121019600.png)增  通过属性复制!(https://img2018.cnblog