Mybatis---主键回填 (*^▽^*)
文章目录
- 业务场景
- 主键回填是什么?
- 主键回填的用法
- 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(),’-’,’’)语句,再执行插入语句,数据全部都返回成功!!! \( ̄︶ ̄)/
第一次记录,完结撒花✿✿ヽ(°▽°)ノ✿
最新文章
- JavaScript,JS如何控制input输入字符限制
- mvn项目Quartz简单上手
- 欢迎使用CSDN-markdown编辑器1212131
- WEB安全基础-CSRF漏洞
- Android之深入WebView
- 微信小程序开发学习笔记002--微信小程序框架解密
- 工作工资不高,很普通的一个我
- IPv6套接字地址结构
- 如何查询硬盘序列号,百度的答案全是错的
- vs2015好看的字体_在VisualStudio中应该使用什么字体
- MyBatisPlus多表关联查询,返回list
- 远程服务器搭建建站助手,windows + 管理助手建站指南
- 索尼6400夜景测试 镜头索尼18-55
- 收发器(Transceiver)架构5——发信机2
- c#webservice接口調用_Windows 桌面应用开发之 C# 调用 WebService 接口
- MySql使用MyCat分库分表(四)分片规则
- 2021年初oracle最新版本是多少_Oracle升级该怎么选版本
- javaFX 调用虚拟键盘
- 白盒测试模板用例:三角形测试
- CCPC-Wannafly Winter Camp Day2 E