文章目录

  • 业务场景
  • 主键回填是什么?
  • 主键回填的用法
    • 1、自增主键(int整数类型)
      • 使用步骤
    • 2、非自增主键(UUID生成varchar字符串类型)
      • 使用步骤

业务场景

主键回填听上去很高级,不妨用一个业务场景来引入概念吧。
在增加操作中,如果设置了主键id是自增的,那么插入数据时id的值一般写null,因为存入数据库时id都会自动+1,看似操作没毛病,非常完美。
但是在购物交易的添加模块这可不兴这样,细想一下在上网买东西时,用户付完钱之后一般都会返回一个订单编号,其实这个订单编号在数据库中就是主键,但是因为在插入数据时id的值写了null,所以订单编号也为null,也就是说返回不了订单编号的数据。
那还是老老实实挨个挨个在插入数据的时候写id呗,如果是批量添加数据呢,面对千万级的插入数据,这显然是不科学滴~
那要不先插入数据再进行查询操作吧,保证能查到数据,emm…有点麻烦,可以但没必要,有需求就有解决方案,开发者早就想到了,我们只要坐享其成就行啦~

主键回填就是用来干这个的,讲完这个业务场景在来思考一下这个专有名词,“主键”+“回填”,谜底就在谜面上,作用就是把插入数据的null主键给填回去,完美实现插入数据为null主键的同时可以查询到主键信息的需求~~


主键回填是什么?

主键回填一般用于增加操作中,把插入数据时插入为null的主键id数据填回去,存入到java对象和主键对应的属性中(数据库主键字段为id则回填的是实体类的id属性),实现添加+查询主键一步到位。


主键回填的用法

有两种,一种是自增主键,一种是非自增主键。

1、自增主键(int整数类型)

最常见的一种,平常我们的主键都是设置为自增,自增为整数类型的,每添加一个数据到数据库中,数据库就会根据自增规则给主键+1

完成主键回填的过程中,映射文件使用到的标签、函数:
1、last_insert_id():mysql 中的函数,作用是获取最近一次插入语句(insert)的自增字段值,即获取最后插入的自增id值

select last_insert_id():表示查询最后一次插入语句(insert)的自增字段值

2、< selectKey > sql语句 < /selectKey >:选择主键标签,嵌套在插入语句中,内部属性如下
(1)order:sql语句在插入语句中的执行顺序,order="AFTER"在这里表示先执行完插入语句后再执行select last_insert_id()语句,因为测试类中插入id属性为null,如果不先执行插入语句,select last_insert_id()语句将查询不到最后的插入语句。

(2)resultType:sql语句执行后的结果类型,resultType="int"在这里表示结果类型为整数类型。

(3)keyProperty:sql语句执行后回填到哪个属性,keyProperty="id"在这里表示通过执行select last_insert_id()把查询到的id值回填到测试类中插入数据的那个空的id属性值。

<selectKey order="AFTER" resultType="int" keyProperty="id">select last_insert_id()
</selectKey>

话不多说,上代码!!!

使用步骤

1、在mybatis_shine数据库中新建一个t_user表,字段如下

 create database mybatis_shine default charset =utf8;create table t_user(id int primary key auto_increment,username varchar(50),password varchar(50),gender tinyint,regist_time datetime)default charset =utf8;

2、新建实体类User类

public class User {private Integer id;private String username;private String password;private Boolean gender;private Date registTime;//构造函数public User() {}public User(Integer id, String username, String password, Boolean gender, Date registTime) {this.id = id;this.username = username;this.password = password;this.gender = gender;this.registTime = registTime;}//get、set方法public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public Boolean getGender() {return gender;}public void setGender(Boolean gender) {this.gender = gender;}public Date getRegistTime() {return registTime;}public void setRegistTime(Date registTime) {this.registTime = registTime;}//重写toString()方法,方便测试打印@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +", gender=" + gender +", registTime=" + registTime +'}';}
}

3、新建UserDao接口

public interface UserDao {//添加操作接口Integer insertUser(User user);
}

4、新建UserMapper.xml映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xxxx.mybatis.dao.UserDao"><insert id="insertUser" parameterType="User"><selectKey order="AFTER" resultType="int" keyProperty="id">select last_insert_id()</selectKey>insert into t_uservalues (#{id} , #{username} , #{password} , #{gender} , #{registTime})</insert>

5、测试类

public class TestMyBatis {public static void main(String[] args) throws Exception{//mybatis//1、加载配置文件,获得读取配置文件的流对象InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");//2、构建 SqlSessionFactory,SqlSession连接对象的工厂SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//3、通过SqlSessionFactory工厂获得连接对象sqlSession,SqlSession sqlSession = sqlSessionFactory.openSession();//4、通过连接对象sqlSession获得dao对应实现类的对象UserDao mapper = sqlSession.getMapper(UserDao.class);//5、调用UserDao接口中的insertUser方法并打印,添加时主键为nullUser user = new User(null,"小宏","520",true,new Date());mapper.insertUser(user);System.out.println(user);//6、提交事务,增删改需要sqlSession.commit();sqlSession.rollback();//7、释放资源sqlSession.close();

6、检验成果
让我们康康数据库,yeah~插入数据成功了!!!

----------分割线------------

再康康打印结果,可以看到先执行插入语句再执行select last_insert_id()语句,插入时主键id为null,但是返回结果时返回了id的数据,amazing╰( ̄▽ ̄)╭


2、非自增主键(UUID生成varchar字符串类型)

首先说一下为什么会有非自增主键吧,我们都知道自增主键唯一且自增,但是也会有亿点点小弊端的,比如说,自增主键只能保证在该系统的主键唯一,当该系统需要和新系统集成,双向同步导入数据时,很难保证原系统的id不发生主键冲突吧,那怎么办呢?不用担心,我们可以用mysql的UUID函数生成一个有效长度为32位字符串类型的全球唯一的识别码,先科普一下什么叫UUID吧。
UUID:是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。
优点:出现数据拆分,合并存储数据的时候,能达到全局的唯一性

完成主键回填的过程中,映射文件使用到的标签、函数:
1、uuid():mysql的一个函数,生成一个有效长度为32位字符串类型的全球唯一的识别码,为什么说是有效长度32位,因为它的总长度为36位,其中有4位是“-”,以“-”为区分分为五组数组,前三组数字从时间戳中生成,第四组数字暂时保持时间戳的唯一性,第五组数字是一个 IEEE 802 节点标点值,保证空间唯一。使用 UUID() 函数,可以生成时间、空间上都独一无二的值。

2、replace(uuid(),’-’,’’):可以消除UUID值的“-”,采用替代的方式,将一个空值的“”替代了“-”,从而生成总长度为32位,有效长度也为32位的UUID值。

select replace(uuid(),’-’,’’):查询生成32位字符串类型的UUID值

3、< selectKey > sql语句 < /selectKey >:选择主键标签,嵌套在插入语句中,内部属性如下

(1)order:sql语句在插入语句中的执行顺序,order="BEFORE"在这里表示先执行select replace(uuid(),’-’,’’)语句后再执行插入语句,因为非自增主键id为null时无法执行插入语句,测试类的id属性不能插入null值,必须先生成uuid主键才能进行插入语句。

(2)resultType:sql语句执行后的结果类型,resultType="string"在这里表示结果类型为字符串类型。

(3)keyProperty:sql语句执行后回填到哪个属性,keyProperty="id"在这里表示通过执行select replace(uuid(),’-’,’’)生成id值回填到测试类中插入数据的那个空的id属性值。

 <!--生成带“-”的UUID值,总长度36位,有效长度32位-->
<selectKey order="BEFORE" resultType="string" keyProperty="id">select uuid()
</selectKey><!--把uuid的值的“-”替换成“”,总长度32位,有效长度32位-->
<selectKey order="BEFORE" resultType="string" keyProperty="id">select replace(uuid(),'-','')
</selectKey>

多说无益,直接上代码!!!

使用步骤

1、在mybatis_shine数据库中新建一个t_student表,字段如下

 create table t_student(id varchar(32) primary key,name varchar(50),gender tinyint)default charset =utf8;

2、新建实体类Student类

public class Student {private String id;private String name;private Boolean gender;public Student() {}public Student(String id, String name, Boolean gender) {this.id = id;this.name = name;this.gender = gender;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Boolean getGender() {return gender;}public void setGender(Boolean gender) {this.gender = gender;}@Overridepublic String toString() {return "Student{" +"id='" + id + '\'' +", name='" + name + '\'' +", gender=" + gender +'}';}
}

3、新建StudentDao接口

public interface StudentDao {Integer insertStudent(Student student);
}

4、新建StudentMapper.xml映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xxxx.mybatis.dao.StudentDao"><insert id="insertStudent" parameterType="Student"><selectKey order="BEFORE" resultType="string" keyProperty="id">select replace(uuid(),'-','')</selectKey>insert into t_studentvalues (#{id} , #{name} , #{gender} )</insert>
</mapper>

5、测试类

public class TestMyBatis {public static void main(String[] args) throws Exception{//mybatis//1、加载配置文件,获得读取配置文件的流对象InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");//2、构建 SqlSessionFactory,SqlSession连接对象的工厂SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//3、通过SqlSessionFactory工厂获得连接对象sqlSession,SqlSession sqlSession = sqlSessionFactory.openSession();//4、通过连接对象sqlSession获得dao对应实现类的对象UserDao mapper = sqlSession.getMapper(UserDao.class);//5、调用StudentDao接口中的insertStudent方法并打印Student student = new Student(null,"小伶",false);studentmapper.insertStudent(student);System.out.println(student);//6、提交事务,增删改需要sqlSession.commit();sqlSession.rollback();//7、释放资源sqlSession.close();

6、检验成果

先康康数据库,yeah yeah~插入数据又成功了!!!

最后一步,康康打印结果,先执行select replace(uuid(),’-’,’’)语句,再执行插入语句,数据全部都返回成功!!! \( ̄︶ ̄)/


第一次记录,完结撒花✿✿ヽ(°▽°)ノ✿

最新文章

  1. JavaScript,JS如何控制input输入字符限制
  2. mvn项目Quartz简单上手
  3. 欢迎使用CSDN-markdown编辑器1212131
  4. WEB安全基础-CSRF漏洞
  5. Android之深入WebView
  6. 微信小程序开发学习笔记002--微信小程序框架解密
  7. 工作工资不高,很普通的一个我
  8. IPv6套接字地址结构
  9. 如何查询硬盘序列号,百度的答案全是错的
  10. vs2015好看的字体_在VisualStudio中应该使用什么字体
  11. MyBatisPlus多表关联查询,返回list
  12. 远程服务器搭建建站助手,windows + 管理助手建站指南
  13. 索尼6400夜景测试 镜头索尼18-55
  14. 收发器(Transceiver)架构5——发信机2
  15. c#webservice接口調用_Windows 桌面应用开发之 C# 调用 WebService 接口
  16. MySql使用MyCat分库分表(四)分片规则
  17. 2021年初oracle最新版本是多少_Oracle升级该怎么选版本
  18. javaFX 调用虚拟键盘
  19. 白盒测试模板用例:三角形测试
  20. CCPC-Wannafly Winter Camp Day2 E

热门文章

  1. 20190713 关于session串号问题的记录
  2. 编程语言排名到底是哪来的?
  3. 201771010137 赵栋《面向对象程序设计(java)》第十八周学习总结
  4. Python类型转换——数据类型转换函数大全
  5. 原生js绑定事件的方法和dom操作
  6. 网络对抗 Exp8 Web基础 20154311 王卓然
  7. Python--进程池与线程池
  8. 随鼠标滚轮缩小和放大图片
  9. docker创建mysql容器
  10. Android AOA协议Android端 流程总结