如何使用JPA注解标注一对一的关系

假设应用场景如下:Node与PageServer是一对一的关系,其中,Node类对应node表如下:


CREATE TABLE `node` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

PageServer类对应page_server表如下:


CREATE TABLE `pageserver` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
`node_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_reference_67` FOREIGN KEY (`node_id`) REFERENCES `node` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

两个类分别如下:


public class Node {
private PageServer pageServer;//PageServer实体

@OneToOne(mappedBy = “node”, fetch = FetchType.LAZY)
public PageServer getPageServer() {
return pageServer;
}

public void setPageServer(PageServer pageServer) {
this.pageServer = pageServer;
}

}

说明

1、该类经过简化,没有全部列出代码,在此我们只关注OneToOne注解及其属性设置。

2、@OneToOne

@OneToOne注解指明 Node 与 PageServer 为一对一关系,@OneToOne注解有五个属性:mappedBy、fetch、targetEntity、cascade 和 optional 。

3、mappedBy=”node”

如果两个实体Bean是双向一对一关联关系,那么使用了mappedBy的一端我们称为关系目标方(方便起见,称为被控方他the Owned),另一端称之为关系拥有方(方便起见,称为控制方 the Owner)。相应的对象称之为被控对象和主控对象。

只有在双向关联时才会使用mappedBy属性,只有OneToOne、OneToMany、ManyToMany上才有mappedBy属性,ManyToOne不存在该属性。

mappedBy标签一定是定义在the owned side(被拥有方的),并指向the owning side(拥有方)的。在本例中,Node类为关系目标方,即被控对象,the Owned 端;PageServer类为关系拥有方,即主控对象, the Owner 。

mappedBy跟JoinColumn/JoinTable总是处于互斥的一方,可以理解为正是由于拥有方中有被拥有方的字段存在,拥有方才拥有了被拥有方。mappedBy这方定义JoinColumn/JoinTable总是失效的,不会建立对应的字段或者表。

4、fetch = FetchType.LAZY

FetchType类型的属性。可选择项包括:FetchType.EAGER 和FetchType.LAZY。

fetch属性默认值是FetchType.EAGER。

FetchType.EAGER表示被控对象(本例是Node类)在主控对象加载的时候同时加载,FetchType.LAZY表示被控对象在被访问时才加载。默认值是FetchType.LAZY。

5、targetEntity

Class类型的属性。定义关系类的类型,默认是该成员属性对应的类类型,所以通常不需要提供定义。


public class PageServer {
private Node node;//所属节点

@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = “node_id”)
@Fetch(FetchMode.JOIN)
public Node getNode() {
return this.node;
}

public void setNode(Node node) {
this.node = node;
}
}

说明

1、cascade属性

该属性定义类和类之间的级联关系。定义的级联关系将被容器视为对当前类对象及其关联类对象采取相同的操作, 而且这种关系是递归调用的。

默认情况下,JPA 不会将任何持续性操作层叠到关联的目标。如果希望某些或所有持续性操作层叠到关联的目标,请将 cascade 设置为一个或多个 CascadeType 实例,其中包括:

CascadeType.ALL
针对拥有实体执行的任何持续性操作均层叠到关联的目标。

CascadeType.MERGE
如果合并了拥有实体,则将 merge 层叠到关联的目标。

CascadeType.PERSIST
如果持久保存拥有实体,则将 persist 层叠到关联的目标。

CascadeType.REFRESH
如果刷新了拥有实体,则 refresh 为关联的层叠目标。

CascadeType.REMOVE
如果删除了拥有实体,则还删除关联的目标。

2、JoinColumn属性

@OneToOne注释只能确定实体与实体的关系是一对一的关系,不能指定数据库表中的保存的关联字段。所以此时要结合@JoinColumn标记来指定保存实体关系的配置。

3、Fetch属性

可设置以下三个值:
@Fetch(FetchMode.JOIN) 会使用left join查询,只产生一条sql语句;
@Fetch(FetchMode.SELECT)   会产生N+1条sql语句;
@Fetch(FetchMode.SUBSELECT)  产生两条sql语句 第二条语句使用id in (…..)查询出所有关联的数据。

参考链接:
http://www.roseindia.net/jpa/eclipsejpaexamples/jparelationship/one-to-one.shtml

此条目发表在java/j2ee分类目录,贴了, 标签。将固定链接加入收藏夹。

发表回复

您的电子邮箱地址不会被公开。

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据