本文共 3110 字,大约阅读时间需要 10 分钟。
前言:
在oracle中一般使用序列(Sequence)来处理主键字段,在MySQL中是没有序列的,但是MySQL有提供了自增长(increment)来实现类似的目的,但也只是自增,而不能设置步长、开始索引、是否循环等。最重要的是一张表只能设置一个字段使用自增,但有的时候我们需要两个或两个以上的字段实现自增(单表多字段自增),MySQL本身是实现不了的,但我们可以用创建一个序列表,使用函数来获取序列的值
(1)新建一个测试表:
1 2 3 4 5 6 7 8 9 10 11 12 | DROP TABLE IF EXISTS `article`; CREATE TABLE `article` ( `id` int (11) NOT NULL , ` name ` varchar (100) DEFAULT NULL , `author` varchar (50) DEFAULT NULL , PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of article -- ---------------------------- INSERT INTO `article` VALUES ( '1' , '程序猿的自我修养' , 'zifangsky' ); |
注意,这里并没有设置主键自增
(2)添加序列表并添加测试数据:
1 2 3 4 5 6 7 8 9 10 11 12 | DROP TABLE IF EXISTS ` sequence `; CREATE TABLE ` sequence ` ( `seq_name` varchar (50) NOT NULL , `current_val` int (11) NOT NULL , `increment_val` int (11) NOT NULL DEFAULT '1' , PRIMARY KEY (`seq_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of board_event_success -- ---------------------------- INSERT INTO ` sequence ` VALUES ( 'seq_article' , '0' , '1' ); |
“seq_name”字段表示一个表的的序列,起名最好跟表的名字相关,并且每个表一条数据
“current_val”字段表示“seq_name”字段所对应的表的当前最大ID(主键ID)
“increment_val”字段表示“seq_name”字段所对应的表的主键ID增长的步长(也就是每次自增+1、+2等)
(3)创建一个用于获取一个表当前最大ID的函数:
1 2 3 4 5 6 7 8 9 10 11 | DROP FUNCTION IF EXISTS `currval`; DELIMITER ;; CREATE FUNCTION `currval`(v_seq_name VARCHAR (50)) RETURNS int (11) begin declare value integer ; set value = 0; select current_val into value from sequence where seq_name = v_seq_name; return value; end ;; DELIMITER ; |
从代码可以看出,这个函数的逻辑很简单,就是根据“seq_name”查询“sequence”这个表的“current_val”这个字段的值
测试:
1 | mysql> select currval( 'seq_article' ); |
很显然,现在输出为0
(4)创建一个用于获取一个表下一个ID的函数:
1 2 3 4 5 6 7 8 9 | DROP FUNCTION IF EXISTS `nextval`; DELIMITER ;; CREATE FUNCTION `nextval`(v_seq_name VARCHAR (50)) RETURNS int (11) begin update sequence set current_val = current_val + increment_val where seq_name = v_seq_name; return currval(v_seq_name); end ;; DELIMITER ; |
这个函数的逻辑也很简单,先是更新“sequence”这个表中的某一个表的序列值,然后再次查询该序列值作为插入数据时的主键ID
测试:
1 | mysql> select nextval( 'seq_article' ); |
很显然,执行这个函数的结果是1,同时“sequence”这个表中的对应的记录也增加了1
使用插件生成一个表对应的Mapper.xml文件时需要修改其生成策略,具体来说就是修改generatorConfig.xml文件,修改一个表的基本数据的生成策略:
1 2 3 4 | < table tableName = "article" domainObjectName = "Article" enableCountByExample = "false" enableDeleteByExample = "false" enableSelectByExample = "false" enableUpdateByExample = "false" > < property name = "ignoreQualifiersAtRuntime" value = "false" /> < generatedKey column = "id" sqlStatement = "select nextval('seq_article');" /> </ table > |
然后运行插件,最后我们可以看到生成的insert方法是这样的:
1 2 3 4 5 6 7 8 9 | < insert id = "insert" parameterType = "cn.zifangsky.model.Article" > < selectKey resultType = "java.lang.Integer" keyProperty = "id" order = "BEFORE" > select nextval('seq_article'); </ selectKey > insert into article (id, name, author ) values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{author,jdbcType=VARCHAR} ) </ insert > |
也就是说使用Mybatis插入数据时,它先是通过 nextval 函数查出待插入数据的主键ID之后,再进行数据的插入
本文转自 pangfc 51CTO博客,原文链接:http://blog.51cto.com/983836259/1889590,如需转载请自行联系原作者