- 业务场景
- 主键回填是什么?
- 主键回填的用法
- 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属性值。
select last_insert_id()
话不多说,上代码!!!
使用步骤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()方法,方便测试打印 @Override public 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映射文件
select last_insert_id() insert into t_user values (#{id} , #{username} , #{password} , #{gender} , #{registTime})
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方法并打印,添加时主键为null User 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属性值。
select uuid() select replace(uuid(),'-','')
多说无益,直接上代码!!!
使用步骤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; } @Override public String toString() { return "Student{" + "id='" + id + ''' + ", name='" + name + ''' + ", gender=" + gender + '}'; } }
3、新建StudentDao接口
public interface StudentDao { Integer insertStudent(Student student); }
4、新建StudentMapper.xml映射文件
select replace(uuid(),'-','') insert into t_student values (#{id} , #{name} , #{gender} )
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(),’-’,’’)语句,再执行插入语句,数据全部都返回成功!!! ( ̄︶ ̄)/
第一次记录,完结撒花✿✿ヽ(°▽°)ノ✿
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)