博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MySQL实现序列(Sequence)效果以及在Mybatis中如何使用这种策略
阅读量:6291 次
发布时间:2019-06-22

本文共 3110 字,大约阅读时间需要 10 分钟。

前言:

在oracle中一般使用序列(Sequence)来处理主键字段,在MySQL中是没有序列的,但是MySQL有提供了自增长(increment)来实现类似的目的,但也只是自增,而不能设置步长、开始索引、是否循环等。最重要的是一张表只能设置一个字段使用自增,但有的时候我们需要两个或两个以上的字段实现自增(单表多字段自增),MySQL本身是实现不了的,但我们可以用创建一个序列表,使用函数来获取序列的值

一 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

二 Mybatis中的序列使用

使用插件生成一个表对应的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,如需转载请自行联系原作者

你可能感兴趣的文章