前言
时隔一月,夏日渐离,秋风起兮,气温渐凉下,断更者忽觉不妥,似有事相忘,却不得要领,夜深,作罢,而转入被中,方得温暖,正欲入眠,忽闻窗外歌声,唱曰:断更有脸,鸽者无罪。吾大怒:谁断更啊?程序员的事,那能叫断更吗?
咕咕咕~
上一节我们讲解了spring-data-jpa最基础的架构和最简单的增删查改的实现,可以发现spring-data-jpa在简单增删查改的实现是非常友好的,甚至根本见不着sql语句的存在,让人直呼NB。
还记得上一节埋的几个坑吗,这一节就先把坑填了。
填坑1:实体类的主键生成策略详解
上一节讲到实体类时,介绍了很多注解的作用及其属性,举的例子是oracle数据库
的实体类。
我们知道,oracle数据库
的主键不是自增的,而是依靠序列来实现主键增长,要想实现一个表的主键是自增长的,我们首先要新建一个此表的序列,让它从1开始(或者从你想要开始的数字开始),每次调用都让序列+1,那么也就实现了主键的自增长。
上一节oracle
的主键自增长的注解是这样的:
1.Oracle自增长主键策略: GenerationType.SEQUENCE
使用如下:
@Id
@Column(name = "ID")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "JPA_USER_S")
@SequenceGenerator(sequenceName = "JPA_USER_S", name = "JPA_USER_S", allocationSize = 1)
private Long id;
解释一下这几个注解如何理解:
-
当生成策略为
SEQUENCE
时,@GeneratedValue
要配合@SequenceGenerator
使用 -
首先
@Id
代表它下方的属性是实体类的主键属性,也就是数据库的主键; -
其次
@Column(name = "ID")
代表此实体类属性对应的数据库的列名是什么,需要进行关系映射; -
再看
@SequenceGenerator(sequenceName = "JPA_USER_S", name = "JPA_USER_S", allocationSize = 1)
,它代表着需要从数据库找到一个序列并在java中映射。sequenceName
属性值:数据库中的序列名name
属性值:这个序列名在java中要映射成的名字allocationSize
属性值:这个序列的自增长步长是几
-
最后看
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "JPA_USER_S")
,它代表着这个主键采取什么样的生成策略。strategy
属性值:采取的主键策略是什么generator
属性值:使用的序列的映射名是什么,这个映射名就是@SequenceGenerator
中name
的值
从上到下理解后有没有理顺这几个注解的先后呢?尤其是@SequenceGenerator
和@GeneratedValue
的关系。
至此oracle
的主键策略注解才算基本讲完,然而并没有结束!
我们知道以序列作为自增长的数据库有Oracle、PostgreSQL、DB2
,不过还有一个耳熟能详的数据库Mysql
是可以不需要序列,直接定义主键自增长的,那么它就需要另一种生成策略。
2.Mysql自增长主键策略:GenerationType.IDENTITY
使用如下:
@Id
@Column(name = "ID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
解释一下:
-
当生成策略为
IDENTITY
时,@GeneratedValue
单独使用 -
@GeneratedValue(strategy = GenerationType.IDENTITY)
,只需要这一个注解就可以实现mysql的主键自增长,我们知道mysql建表的时候可以给主键声明auto_increment
,这就实现了自增长了,所以注解也相对简单。
在@GeneratedValue
注解中我们只需要生成策略为IDENTITY
,即可完成mysql数据库的主键自增长。
3.万能自增长主键策略:GenerationType.TABLE
使用如下:
@Id
@Column(name = "ID")
@GeneratedValue(strategy = GenerationType.TABLE, generator = "sequence_table")
@TableGenerator(name = "sequence_table",
allocationSize = 1,
table = "sequence_table",
pkColumnName = "sequence_name",
valueColumnName = "sequence_count")
private Long id;
解释一下:
- 当生成策略为
TABLE
时,@GeneratedValue
要配合@TableGenerator
使用 @TableGenerator(name = "id_sequence", allocationSize = 1, table = "sequence_table",pkColumnName = "sequence_max_id", valueColumnName = "sequence_count")
,它代表着需要在数据库建立一张索引表来帮助我们实现主键自增name
属性值:建立的索引表在java中要映射成的名字allocationSize
属性值:这个序列的自增长步长是几table
属性值:建立的序列表的表名,缺省值:SEQUENCE
pkColumnName
属性值:建立的序列表的第一个列的列名,此列自动填充需要序列作为主键自增长的表的表名,缺省值:SEQ_NAME
valueColumnName
属性值:建立的序列表的第二个列的列名,此列自动填充pkColumnName
所代表的表的下一个序列值,缺省值:SEQ_COUNT
@GeneratedValue(strategy = GenerationType.TABLE, generator = "id_sequence")
,代表着这个主键采取什么样的生成策略,和Oracle中的解释一样strategy
属性值:采取的主键策略是什么generator
属性值:使用的映射名是什么,这个映射名就是@SequenceGenerator
中name
的值
一通解释看下来,可能会有点蒙,用示例来解释会更加直观:
TABLE生成策略示例:
3.1 新建一个部门实体类:JpaDepartment(属性很简单:id、部门名、五个系统字段)
@Data
@Entity
@Table(name = "JPA_DEPARTMENT")
@EntityListeners(AuditingEntityListener.class)
public class JpaDepartment {
@Id
@Column(name = "ID")
@GeneratedValue(strategy = GenerationType.TABLE, generator = "sequence_table")
@TableGenerator(name = "sequence_table",
allocationSize = 1,
table = "sequence_table",
pkColumnName =