Skip to content

2.3 generatedvalue

isea533 edited this page Feb 5, 2018 · 2 revisions

2.3 主键策略

在 2.2 中介绍了所有其他注解的作用和用法,由于主键策略比较复杂,单独用一节来阐述。

首先主键策略和数据库关系很大,有些数据库支持主键自增,而有些数据库只能通过序列来获得。

2.3.1 JDBC 支持通过 getGeneratedKeys 方法取回主键的情况

这种情况首先需要数据库支持自增,其次数据库提供的 JDBC 支持 getGeneratedKeys 方法。

常见的如 MySql,SqlServer 支持这种模式。

这种情况下,配置主键策略最简单。

用法如下:

@Id
@GeneratedValue(generator = "JDBC")
private Long id;

为了让大家容易理解这里配置和 MyBatis 写法的关系,大家可以看看对应生成的 XML 代码:

<insert id="insert" useGeneratedKeys="true" keyProperty="id">
    insert into country (id, countryname, countrycode)
    values (#{id},#{countryname},#{countrycode})
</insert>

SqlServer 中使用时,需要设置 id 的 insertable=false

2.3.2 支持自增的数据库

支持自增的数据库列表如下:

  • DB2: VALUES IDENTITY_VAL_LOCAL()
  • MYSQL: SELECT LAST_INSERT_ID()
  • SQLSERVER: SELECT SCOPE_IDENTITY()
  • CLOUDSCAPE: VALUES IDENTITY_VAL_LOCAL()
  • DERBY: VALUES IDENTITY_VAL_LOCAL()
  • HSQLDB: CALL IDENTITY()
  • SYBASE: SELECT @@IDENTITY
  • DB2_MF: SELECT IDENTITY_VAL_LOCAL() FROM SYSIBM.SYSDUMMY1
  • INFORMIX: select dbinfo('sqlca.sqlerrd1') from systables where tabid=1

这个列表只是列举了比较常见的数据库,其他类似的也支持。

列表数据库名字后面对应的 SQL 是插入后取 id 的 SQL 语句

这类数据库主键策略配置示例如下:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

除此之外,这种用法还要配合 IDENTITY 参数(以及 ORDER 参数),这个参数值需要配置为对应的数据库,就是上面列表中的名字,具体的配置方法看后面章节的内容。

这种配置对应的 XML 形式为:

<insert id="insertAuthor">
    <selectKey keyProperty="id" resultType="int" order="AFTER">
      SELECT LAST_INSERT_ID()
    </selectKey>
    insert into country (id, countryname, countrycode)
    values (#{id},#{countryname},#{countrycode})
</insert>

IDENTITY 参数以及 ORDER 参数会决定 selectKey 中的 SQL 和 order 属性的值(这里是 AFTER)。

2.3.3 通过序列和任意 SQL 获取主键值

像 Oracle 中通过序列获取主键就属于这种情况,实际上 2.3.2 中的 SQL 也可以在这里配置。

除了类似序列获取值外,还可以是获取 UUID 的 SQL 语句,例如 select uuid()

2.3.3 和 2.3.2 的区别主要在于,2.3.2 是插入表之后才有 id 的值,2.3.3 是插入数据库前需要获取一个值作为主键。

在 Oracle 中,我们可以用下面的方式进行配置:

@Id
@GeneratedValue(
  strategy = GenerationType.IDENTITY,
  generator = "select SEQ_ID.nextval from dual")
private Integer id;

除此之外也要配置一个 ORDER 全局参数,2.3.2 中提到的 AFTER,在 2.3.3 中需要配置为 BEFORE,具体配置方式看后面章节的内容。

这种配置对应的 XML 代码如下:

<insert id="insertAuthor">
  <selectKey keyProperty="id" resultType="int" order="BEFORE">
    select SEQ_ID.nextval from dual
  </selectKey>
  insert into country (id, countryname, countrycode)
  values (#{id},#{countryname},#{countrycode})
</insert>

这种用法中,values 中必须出现主键的值,否则就插不到数据库。

除了 Oracle 这种外,还有一种更普遍的用法,就是使用 UUID。

例如下面的配置:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY,generator = "select uuid()")
private String id;

注意 SQL 返回值类型和这里接收的类型(String)一致。

2.3.4 TODO 增加一种新的注解,能够独立配置 SQL 和 ORDER

由于 2.3.2 和 2.3.3 中的配置都依赖于 ORDER,并且这两种情况下的值相反,因此如果想要同时使用就会出现问题,因此提供一个新的专用注解来替代 2.3.2 和 2.3.3 是很有必要的。

这个功能待定,准备包含在 4.0 版本中。