在前面章节已经介绍了 JPA 大部分的注解,以及注解的用法。接下来我们将利用这些注解去实现实体类和数据表之间的简单映射。
这里的映射也称对象关系映射。对象关系映射(英语:Object Relational Mapping,简称 ORM,或 O/RM,或 O/R mapping),是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。
从效果上说,它其实是创建了一个可在编程语言里使用的 “虚拟对象数据库”。使用者不需要直接去操作数据库,直接操作对象即可。ORM 框架会自动帮我们把对对象的操作应用到数据库中。
对象数据库是一种以对象形式表示信息的数据库。对象数据库的数据库管理系统被称为 ODBMS 或 OODBMS。
两个主要原因让用户使用对象数据库技术。
首先,关系数据库在管理复杂数据时显得笨重。
其次,被应用软件操作的数据一般是用面向对象的编程语言如 C++, Java, Delphi 和 C# 写成,而那些用来转化数据表示和关系数据库元组的代码很冗繁,执行时也有不少耗时。
单向:从A可以到导航到B,B不能导航到A。例如:以老师和学生为例,老师知道自己有那些学生,而学生却不知道他的老师。如下:
public class Teacher { //...省略... private List<Student> studentList; } public class Student { //...省略... }
上面代码中,在 Teacher 类中能够访问 Student,然而 Student 不能访问 Teacher,因此为单向。
双向:从A可以导航到B,B也能导航到A。例如:以老师和学生为例,老师知道自己有那些学生,学生也知道他的老师是谁。如下:
public class Teacher { //...省略... private List<Student> studentList; } public class Student { //...省略... private Teacher teacher; }
上面代码中,在 Teacher 类中能够访问 Student,并且 Student 中也能访问 Teacher,所以是双向的。
一对一:比如说一个班级有很多学生,他们分别有不同的学号。一个学生对应一个学号,一个学号对应一个学生;通过学号能找到学生,通过学生也能得到学号,不会重复。这里学生和学号的关系就是一对一。要实现一对一关系,需要在主表中添加一个外键。
一对多:比如说一个班级有很多学生,可是这个班级只有一个班主任。在这个班级中随便找一个人,就会知道他们的班主任是谁;知道了这个班主任就会知道有哪几个学生。这里班主任和学生的关系就是一对多。要实现一对多需要在多的一方的表里面添加外键。
多对一:比如说一个班级有很多学生,可是这个班级只有一个班主任。在这个班级中随便找一个人,就会知道他们的班主任是谁;知道了这个班主任就会知道有哪几个学生。这里学生和班主任的关系就是多对一。要实现多对一需要在多的一方的表里面添加外键。
多对多:比如说一个班级有很多学生,他们有语文课、数学课、英语课等很多课。一门课有很多人上,一个人上很多门课。这里学生和课程的关系就是多对多。多对多关系必须要通过中间表表来表示它们之间的关系。
下面仅仅介绍怎样使用 JPA 映射单张表,关于一对一、一对多和多对多将在后续章节逐一展开。
假如我们有一张简单的 user 用户表,现在使用 JPA 提供的注解将它映射到 User 实体。如下:
CREATE TABLE `user` ( `id` int NOT NULL AUTO_INCREMENT , `name` varchar(20) NULL , `sn` varchar(50) NOT NULL , `hiredate` datetime NULL , PRIMARY KEY (`id`) );
@Entity // 根据需求,对类和表做相关映射 (如:表名) @Table(name="user") public class User { // 标识该字段为主键列对应的字段 @Id // 指定主键的生成策略 @GeneratedValue(strategy = GenerationType.AUTO) // 为当前字段和对应的列做映射(如:列名,列的长度等) @Column(name = "id") private Long id; @Column(name = "name",length = 20) private String name; @Column(name = "sn",nullable = false) private String sn; // 对日期类型做映射 @Temporal(TemporalType.DATE) private Date hiredate; }
上述实例中,JPA 会扫描到拥有 @Entity 注解的类,将其作为需要持久化的类,由 JPA 管理它的持久化。其中:
@Table 注解定义该实体对应哪张数据表,如果没有为实体类指定 @Table 注解,则实体类将使用默认值表名。
@Id 表示该字段为主键字段。如果不指定该注解,IDEA 会提示错误信息 “Persistent entity 'User' should have primary key”;但是,依然可以正确执行;
@GeneratedValue 注解用来指定主键生成策略,如:自增长、序列、数据表(JPA 通过一张表来维护主键值,性能稍差)
关于更多定义实体的注解,可以参考前一大章节。