场景:springboot+mybatis项目中,需要获取自增id作为表单数据自增id主键,则可以通过自定义nextval函数来进行调用。
一、数据库准备:定义序列表与nextval自增id函数
--定义序列表TPL_SEQ_PROPERTY_S
DROP TABLE IF EXISTS TPL_SEQ_PROPERTY_S;
CREATE TABLE `TPL_SEQ_PROPERTY_S`(
`ID` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`SEQ_NAME` CHAR(20) NOT NULL DEFAULT 'SEQ',
PRIMARY KEY(`ID`) ) AUTO_INCREMENT=1;---设置起点从1开始
---UNSIGNED :无符号整数,非负数,可以扩大正数的范围,如有符号的TINYINT类型能表示-128至128,而无符号(unsigned)的TINYINT类型就可以表示0至256了
--定义函数NEXTVAL
CREATE DEFINER=`root`@`%` FUNCTION `NEXTVAL`() RETURNS BIGINT(20) DETERMINISTIC
BEGIN
DECLARE current BIGINT;
INSERT INTO TPL_SEQ_PROPERTY_S(SEQ_NAME) VALUES ('SEQ');
SELECT LAST_INSERT_ID() INTO current;
RETURN current;
END
LAST_INSERT_ID():MySQL内置函数,获取MySQL生成的最后一个插入id的值
二、创建dao层接口与对应的数据映射文件XML
后台数据库的工作做好之后,接着就到springboot项目中resources目录下的IpowerDao.xml进行函数调用(xml文件在resources目录下,创建路径与对应的dao层一致),在此之前先创建好dao层接口类IpowerDao.java,如下:
package com.power.it.app.dao;
import org.springframework.stereotype.Repository;
@Repository
public interface IpowerDao{
//获取自增ID序列
public int getSeq();
}
IpowerDao.xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.power.it.app.dao.IpowerDao">
<select id="getSeq" resultType="java.lang.Integer" useCache="false" flushCache="true">
SELECT SCHEMA.NEXTVAL();
</select>
</mapper>
这里有个问题需要重点注意,我们springboot项目一般都有做事务管理,而这个自增ID函数的实现逻辑是先插入序列表一条件数据,ID字段则会自增长,再通过调用LAST_INSERT_ID()内置函数取到最后插入的数据的ID值,事务还未提交完成(当全部程序执行完成才会提交),调用内置函数取值则会一直取到最后插入之前的那个ID值,需要通过设置两个参数进行清空缓存。否则就无法取到自增ID值。
(1)当为select语句时:
flushCache默认false,本条语句被调用后不会清空本地缓存和二级缓存。
useCache默认true,会把本条语句的结果进行二级缓存。
(2)当为insert、update、delete语句时:
flushCache默认true,本条语句被调用后会导致本地缓存和二级缓存被清空。
(3)select语句的时候,如果没有去配置flushCache、useCache,那么默认是启用缓存的,所以需要人工修改配置使其清空缓存,修改结果类似下面:
<select id="getSeq" resultType="java.lang.Integer" flushCache="true" useCache="false"> SELECT SCHEMA.NEXTVAL();
</select>(4)update语句设置 flushCache="false",则当你更新后,查询的数据数据还是老的数据。
service 层与 controller层则根据业务具体需求来进行调用dao层的数据接口即可