|
| 1 | +#通用 Mapper UUID 简单示例 |
| 2 | +通用 Mapper 中对 UUID 的用法主要提到了一种专有的写法,如下写法: |
| 3 | +```java |
| 4 | +@GeneratedValue(generator = "UUID") |
| 5 | +``` |
| 6 | +这种方式实现很容易理解,就是在你 insert 之前,调用 UUID 的公共方法在 `<bind>` 标签中生成了一个值,插入到了数据库,由于这个值是临时的,并没有 `set` 到对象,因此这种方式是不支持回写的。 |
| 7 | + |
| 8 | +由于回写方式很常见,因此用这种方式很难满足要求。 |
| 9 | + |
| 10 | +上面这些在文档中都提到了。 |
| 11 | + |
| 12 | +而且在文档中也提到了一种可以回写的方式,由于很多人不理解或者尝试失败,因此很早就有必要写一篇如何使用可回写 UUID 的方式(我曾经远程协助一个朋友解决过这个问题,这个朋友答应我把自己的用法写下来分享给大家,可惜食言了)。 |
| 13 | + |
| 14 | +##可回写的 UUID |
| 15 | +最简单的可回写 UUID 方式就是像 Oracle 序列那样直接写一个返回 UUID 的 SQL 就能实现,这是第一种写法: |
| 16 | +```java |
| 17 | +@Id |
| 18 | +@GeneratedValue(strategy = GenerationType.IDENTITY,generator = "select uuid()") |
| 19 | +private String id; |
| 20 | +``` |
| 21 | +使用这种方式的时候必须注意,由于是执行 SQL,所以底层是使用 `<selectKey>` 实现的,并且因为需要先得到 UUID 的值才能插入数据库,因此还需要配置 `ORDER` 属性,使用 Java 方式配置时,用下面的方式进行配置: |
| 22 | +```java |
| 23 | +Config config = new Config(); |
| 24 | +// 其他配置 |
| 25 | +// 主键自增回写方法执行顺序,默认AFTER,可选值为(BEFORE|AFTER) |
| 26 | +config.setOrder("BEFORE"); |
| 27 | +mapperHelper.setConfig(config); |
| 28 | +``` |
| 29 | + |
| 30 | +使用 Spring 方式进行配置时如下: |
| 31 | +```xml |
| 32 | +<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer"> |
| 33 | + <property name="basePackage" value="com.isea533.mybatis.mapper"/> |
| 34 | + <property name="properties"> |
| 35 | + <value> |
| 36 | + mappers=tk.mybatis.mapper.common.Mapper |
| 37 | + ORDER=BEFORE |
| 38 | + </value> |
| 39 | + </property> |
| 40 | +</bean> |
| 41 | +``` |
| 42 | +注意是增加 `ORDER=BEFORE` 这一行,如果你还有其他配置,都可以按这种方式一行一个 `key=value`。 |
| 43 | + |
| 44 | +这么配置以后就可以正确的获取 UUID 的值了。 |
| 45 | + |
| 46 | +##任意类型的主键回写值 |
| 47 | +你可能没注意到上面 UUID 类型的主键中,`id` 属性的类型是 `String`,因为`select uuid()` 返回的字符串,所以 Java 中的类型要和数据库类型匹配。 |
| 48 | + |
| 49 | +因此,如果你使用一个 `select myId()` 函数返回一个自定义类型的主键值,你需要让 Java 中的类型和这个匹配。 |
| 50 | + |
| 51 | +##通用主键 SQL 配置 |
| 52 | +如果你每一个实体类中都有一个 `id` 属性,并且配置的注解都一样,都执行同样的 SQL 去返回值。如果都去配置这个注解会很麻烦。想要解决这种重复性配置,最简单的方式就是提取基类,让使用相同方式主键策略的实体类继承同一个基类就能解决。 |
| 53 | + |
| 54 | +但是如果你需要适用不同的数据库,这种方式麻烦点的解决办法就是针对不同的数据库创建不同的基类,放在不同的项目中,但是使用相同的包名,具体应用到生产环境时使用对应数据库的基类 jar 包就可以。除此之外还有一种方式,这种方式就是使用 `IDENTITY`,这个参数用于配置取回主键的方式。 |
| 55 | + |
| 56 | +默认提供的 `IDENTITY` 可选值参考文档 [GenerationType.IDENTITY](http://git.oschina.net/free/Mapper/blob/master/wiki/mapper3/3.Use.md#2-generatedvalue-strategy-=-generationtype-identity-_7) 。 |
| 57 | + |
| 58 | +这个参数除了这些可选值外,还可以是可以执行的 SQL,也就是说最前面的配置方式可以改为: |
| 59 | +```java |
| 60 | +@Id |
| 61 | +@GeneratedValue(strategy = GenerationType.IDENTITY) |
| 62 | +private String id; |
| 63 | +``` |
| 64 | +在 Java 方式中用下面的方式进行配置: |
| 65 | +```java |
| 66 | +Config config = new Config(); |
| 67 | +// 其他配置 |
| 68 | +config.setIDENTITY("select uuid()"); |
| 69 | +// 主键自增回写方法执行顺序,默认AFTER,可选值为(BEFORE|AFTER) |
| 70 | +config.setOrder("BEFORE"); |
| 71 | +mapperHelper.setConfig(config); |
| 72 | +``` |
| 73 | +使用 Spring 方式进行配置时如下: |
| 74 | +```xml |
| 75 | +<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer"> |
| 76 | + <property name="basePackage" value="com.isea533.mybatis.mapper"/> |
| 77 | + <property name="properties"> |
| 78 | + <value> |
| 79 | + mappers=tk.mybatis.mapper.common.Mapper |
| 80 | + IDENTITY=select uuid() |
| 81 | + ORDER=BEFORE |
| 82 | + </value> |
| 83 | + </property> |
| 84 | +</bean> |
| 85 | +``` |
| 86 | +这里仍然要注意设置 `ORDER=BEFORE`,如果你用 `IDENTITY` 提供的那些可选参数,就不要设置(默认为`AFTER`),可选参数中仍然是针对的数据库支持自增的情况,那些情况仍然是插入数据库后才会有主键值,这点一定要明白! |
| 87 | + |
| 88 | +在这种情况下,如果换了数据库,只需要修改一下配置就能解决,例如 SQL SERVER 的: |
| 89 | +```sql |
| 90 | +IDENTITY=select replace(newid(), '-', '') |
| 91 | +``` |
| 92 | + |
| 93 | +##总结 |
| 94 | +关于 UUID 的内容就上面这些,还需要提醒一点的就是由于 `ORDER` 是一个全局的配置,所以使用时要注意保证所有主键方式都是一致的 `ORDER` 方式,主键自增的时候使用 `@GeneratedValue(generator = "JDBC")` 这种方式通过 JDBC 接口去获取返回值更好。当然使用批量插入时,MySql 支持多主键回写,但是 SqlServer 仅能返回最后一个插入的主键,所以选择使用某种方式时,一定要有所了解,做好测试,避免数据库差异带来的问题。 |
0 commit comments