博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
@OneToMany、@ManyToOne以及@ManyToMany讲解
阅读量:6174 次
发布时间:2019-06-21

本文共 4277 字,大约阅读时间需要 14 分钟。

一、一对多(@OneToMany)

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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,代码如下:

1
2
3
4
5
6
7
8
@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的定义代码如下:

1
2
3
4
5
6
7
@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,如下: 

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

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

1
2
3
4
5
6
7
8
9
10
11
@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,定义如下:

1
2
3
4
5
6
7
8
9
@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) 默认关联
在数据库底层为两张表添加约束,如下:

1
2
3
4
5
6
7
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实体如下:

1
2
3
4
5
6
7
8
9
10
@Entity
@Table
(name=
"address"
)
public
class
AddressEO
implements
java.io.Serializable {
     
  
@ManyToOne
(cascade = { CascadeType.ALL })
  
@JoinColumn
(name=
"customer_id"
)
  
private
CustomerEO customer;
     
  
// ...
}

@ManyToOne定义如下:

1
2
3
4
5
6
7
@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实体修改为:

1
2
3
4
5
6
7
8
9
@Entity
@Table
(name=
"customer"
)
public
class
CustomerEO {
     
  
@OneToMany
(mappedBy=
"customer"
)
  
private
Collection<AddressEO> addresses =
new
ArrayList<AddressEO>();
     
  
// ...
}

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

四、多对多(@ManyToMany)

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

1
2
3
4
5
6
7
@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值的集合。

转载地址:http://tamba.baihongyu.com/

你可能感兴趣的文章
CYQ.Data 轻量数据层之路 框架开源系列 索引
查看>>
zabbix(2)使用自带模板完成基本监控
查看>>
安装rrdtool出现的错误
查看>>
木马隐藏地点全搜查
查看>>
Subversion版本控制
查看>>
奇怪的打印纸盘故障
查看>>
hyperledger v1.0.5 区块链运维入门(一)
查看>>
Mybatis-mapper-xml-基础
查看>>
5. GC 调优(基础篇) - GC参考手册
查看>>
Windows 7 XP 模式颜色质量只有16位的解决
查看>>
SonicWall如何安全模式升级防火墙
查看>>
Linux IPC实践(3) --具名FIFO
查看>>
从Atlas到Microsoft ASP.NET AJAX(6) - Networking, Application Services
查看>>
成长之路---写好一个类
查看>>
读取 java.nio.ByteBuffer 中的字符串(String) 写入方式flash.utils.ByteArray.writeUTF
查看>>
范围管理和范围蔓延
查看>>
android90 bind方式启动服务service调用service里的方法
查看>>
前端开发薪资之各地区对比(图文分析)(share)
查看>>
对做“互联网产品”的一些想法
查看>>
SPI协议及其工作原理浅析【转】
查看>>