一、javax.persistence概况介绍
虽然Spring Data JPA已经帮我们对数据的操作封装得很好了, 约定大于配置思想,帮我们默认了很多东西。
JPA(Java持久性API) 是存储业务实体关联的实体来源。它显示了如何定义一个面向普通 Java对象(POJO)作为一个实体,以及如何与管理关系实体提供一套 标准。因此,javax.persistence下面的有些注解还是必须要去了解 的,以便于更好地提高工作效率。
(1)javax.persistence位于hibernate-jpa-**.jar包里面,可以通过Intellij Idea的maven插件直接分析一下maven的依赖,也可以用$ mvn dependency:tree分析,例如:
![](https://i-blog.csdnimg.cn/blog_migrate/0307dc77d28cf49807322337029c25c9.png)
(2)通过Intellij Idea的Diagram来看一下此模块类的关键关系。
![](https://i-blog.csdnimg.cn/blog_migrate/c9b65673b43787535f1c0e509c0c2989.png)
(3)图显示了JPA的类的层次结构,包括核心类和JPA接口。
![](https://i-blog.csdnimg.cn/blog_migrate/320111381074a802482c8896c461aa1c.png)
每个在上述架构的显示单元。
![](https://i-blog.csdnimg.cn/blog_migrate/12f5bb81918404544df763f2014771f6.png)
上述的类和接口用于存储实体到数据库的一个记录,帮助程序员通过减少自己编写的代码将数据存储到数据库中,使他们能够专注于更重要的业务活动代码,如数据库表映射的类编写代码。
下面我们主要介绍一下在Entity里面常用的注解,对于其他没有介绍到的注解,建议读者直接到包的源码里面进行查找和分析。
二、基本注解
基本注解包括@Entity、@Table、@Id、@IdClass、@GeneratedValue、@Basic、@Transient、@Column、@Temporal、 @Enumerated、@Lob。
2.1 @Entity
|
@Entity定义对象将会成为被JPA管理的实体,将映射到指定的数据库表。
2.2 @Table
@Table指定数据库的表名。
2.3 @Id
@Id定义属性为数据库的主键,一个实体里面必须有一个。
2.3 @IdClass
@IdClass利用外部类的联合主键。
作为复合主键类,要满足以下几点要求。
- 必须实现Serializable接口。
- 必须有默认的public无参数的构造方法。
- 必须覆盖equals和hashCode方法。equals方法用于判断两个对象是否相同,EntityManger通过find方法来查找Entity时是根据equals的返回值来判断的。在本例中,只有对象的name和 email值完全相同或同一个对象时才返回true,否则返回 false。hashCode方法返回当前对象的哈希码,生成的hashCode相同的概率越小越好,算法可以进行优化。
用法
① 我们假设UserBlog的联合主键是createUserId和title,新增一个UserBlogKey的类。UserBlogKey.class代码如下:
② UserBlogEntity.java要稍加改动:实体类上需要加@IdClass注解,主键上都得加@Id。
![](https://i-blog.csdnimg.cn/blog_migrate/c92df9e0c914a261c5441d24e64b3e1b.png)
③ UserBlogRepository中的改动如下:
④ 使用的时候:
因为Jpa默认会提供根据主键信息进行查询内容的方法,所以如果表的主键为双主键的时候,相应的实现主键查询的方法也要进行调整,要和主键的类型一致。这就是为什么③ ④要进行调整的原因。
2.4 @GeneratedValue
@GeneratedValue为主键生成策略,例如:
GenerationType一共有以下4个值:
IDENTITY:主键由数据库自动生成(主要是自动增长型)
SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。
AUTO:主键由程序控制
TABLE:使用一个特定的数据库表格来保存主键
2.5 @Basic 、@Transient
@Basic表示属性是到数据库表的字段的映射。如果实体的字段上没有任何注解,默认即为@Basic。
@Transient表示该属性并非一个到数据库表的字段的映射,表示非持久化属性,与@Basic作用相反。JPA映射数据库的时候忽略它。
2.6 @Column
@Column定义该属性对应数据库中的列名。
2.7 @Temporal
@Temporal用来设置Date类型的属性映射到对应精度的字段。
(1)@Temporal(TemporalType.DATE)映射为日期∥date(只有日期)。
(2)@Temporal(TemporalType.TIME)映射为日期∥time(只有时间)。
(3)@Temporal(TemporalType.TIMESTAMP)映射为日期∥datetime(日期+时间)。
![](https://i-blog.csdnimg.cn/blog_migrate/25b63f042482f53ec343fd2f95799719.png)
2.8 @Enumerated
@Enumerated很好用,直接映射enum枚举类型的字段。
(1)看源码:
(2)看例子:
这时插入两条数据,数据库里面的值是MAIL/FMAIL,而不是“男性”/“女性”。如果我们用@Enumerated(EnumType.ORDINAL),那么
这时数据库里面的值是0,1。但是实际工作中,不建议用数字下标,因为枚举里面的属性值是会不断新增的,如果新增一个,位置变化了就惨了。
2.9 @Lob
@Lob 将属性映射成数据库支持的大对象类型,支持以下两种数据库类型的字段。
(1)Clob(Character Large Ojects)类型是长字符串类型,java.sql.Clob、Character[]、char[]和String将被映射为Clob类型。
(2)Blob(Binary Large Objects)类型是字节类型, java.sql.Blob、Byte[]、byte[]和实现了Serializable接口的类型将被映射为Blob类型。
(3)Clob、Blob占用内存空间较大,一般配合@Basic(fetch=FetchType.LAZY)将其设置为延迟加载。
三、关联关系注解(一般不使用了解即可)
关联关系注解包括@JoinColumn、@OneToOne、@OneToMany、 @ManyToOne、@ManyToMany、@JoinTable、@OrderBy。
3.1 @JoinColumn定义外键关联的字段名称
用法:@JoinColumn主要配合@OneToOne、@ManyToOne、 @OneToMany一起使用,单独使用没有意义。
@JoinColumns定义多个字段的关联关系。
3.2 @OneToOne关联关系
用法:@OneToOne需要配合@JoinColumn一起使用。注意:可以双向关联,也可以只配置一方,需要视实际需求而定。
假设一个部门只有一个员工。Department的内容如下:
![](https://i-blog.csdnimg.cn/blog_migrate/d353ad5575f583a5d296aabe2901037d.png)
employee_id指的是Department里面的字段,而referencedColumnName="id"指的是Employee表里面的字段。
如果需要双向关联,Employee的内容如下:
当然也可以不选用mappedBy,和下面效果是一样的:
![](https://i-blog.csdnimg.cn/blog_migrate/ee07cbe6c7649aed86eb359c5004f8ef.png)
3.3 @OneToManyg与@ManyToOne关联关系
@OneToMany与@ManyToOne可以相对存在,也可只存在一方。
@OneToMany源码语法如下:
使用示例,必须和@JoinColumn配合使用才有效。
![](https://i-blog.csdnimg.cn/blog_migrate/2bd50ebf7cf5f7353f958634392983d0.png)
3.4 @ManyToMany关联关系
源码语法如下:
@ManyToMany表示多对多,和@OneToOne、@ManyToOne一样也有单向、双向之分。单向双向和注解没有关系,只看实体类之间是否相互引用。
(2)示例:一个博客可以拥有多个标签,一个标签也可以使用在多个博客上,Blog和Tag就是多对多关系。
BlogTagRelation为中间关联关系表blog_tag_relation对应的实体。
3.5 关于关系查询的一些坑
- 所有的注解要么全配置在字段上,要么全配置在get方法上,不能混用,混用就会启动不起来,但是语法配置没有问题。
- 所有的关联都是支持单向关联和双向关联的,视具体业务场景而定。JSON序列化的时候使用双向注解会产生死循环,需要人为手动转化一次,或者使用@JsonIgnore。
- 在所有的关联查询中,表一般是不需要建立外键索引的。@mappedBy的使用需要注意。
- 级联删除比较危险,建议考虑清楚,或者完全掌握。
- 不同的关联关系的配置,@JoinClumn里面的name、referencedColumnName代表的意思是不一样的,很容易弄混,可以根据打印出来的SQL做调整。
- 当配置这些关联关系的时候建议大家直接在表上面,把外键建好,然后通过后面我们介绍的开发工具直接生成,这样可以减少自己调试的时间。