• mybatis 08: 返回主键值的insert操作 + 利用UUID获取字符串(了解)


    返回主键值的insert操作

    应用背景

    image

    • 图示说明
      • 在上述业务背景下,涉及两张数据表的关联操作:用户表 + 用户积分表
      • 传统操作:在对用户表执行完插入语句后,再次查询该用户的uid,将该uid作为外键,最后插入积分数据到用户积分表
        • 数据库操作次数:3次
      • 优化操作:在对用户表执行完插入语句后返回该用户的主键uid,将该uid作为外键,再插入用户积分数据到用户积分表
        • 数据库操作次数:2次
      • 优化操作可以减少对数据库的操作次数

    代码实现

    UsersMapper.java接口

    package com.example.mapper;
    
    import com.example.pojo.User;
    import org.apache.ibatis.annotations.Param;
    
    import java.util.List;
    
    /**
     * 数据访问层的接口,定义对数据库完成的CRUD的操作
     */
    public interface UsersMapper {
    
        //插入用户数据并返回用户id
        int insertAndReturnId(User user);
    }
    
    • 接口代码说明
      • 方法中int类型的返回值并不是返回的用户id,而是插入操作执行后受影响的记录条数
      • 至于返回的用户id会通过特殊的sql标签中的属性来指定接收者
      • 后文中的映射文件会具体的介绍该特殊的sql标签及其属性,后文的测试输出结果中,也可以看到该特殊标签及其属性的底层作用原理
      • 在SqlMapConfig.xml核心配置文件中添加日志输出,方便查看sql标签的底层解析
    
    configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <configuration>
        
        
        
        <settings>
            <setting name="logImpl" value="STDOUT_LOGGING"/>
        settings>
    
    configuration>
    

    UsersMapper.xml映射文件

    
    mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.example.mapper.UsersMapper">
    
        
        
        <insert id="insertAndReturnId" parameterType="user">
            <selectKey keyProperty="id" resultType="int" order="AFTER">
                select
                    last_insert_id()
            selectKey>
            insert into
                    users(username, birthday, sex, address)
            	values
            		(#{userName}, #{birthday}, #{sex}, #{address})
        insert>
    mapper>
    
    • 映射文件说明
      • 在原先的insert标签中嵌套了selectKey标签(上文提到的特殊标签),关于该子标签的属性说明
        • keyProperty属性:指明子标签的返回结果由入参中的哪个属性来接收
        • resultType属性:子标签的返回结果的类型
        • order属性:子标签相对于外层标签中的sql语句执行的先后顺序
      • last_insert_id():mysql内置的函数,返回插入的最后一条记录的自增主键id值
        • 关于sql标签的执行顺序以及内层标签的返回值到底由谁来接收,可以看测试结果输出的底层内容

    测试代码

    package com.example.mapper;
    
    import com.example.pojo.User;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.List;
    
    public class TestUsersMapper {
    
        //时间刷
        SimpleDateFormat date = new SimpleDateFormat("yyyy-MM-dd");
    
        //SqlSession对象
        SqlSession sqlSession;
    
        //mybatis动态代理对象
        UsersMapper usersMapper;
    
        //获取SqlSession
        @Before
        public void getSqlSession() throws IOException {
            //读取核心配置文件
            InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
            //创建SqlSessionFactory对象
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
            //获取SqlSession
            sqlSession = factory.openSession();
            //获取mybatis动态代理对象
            usersMapper = sqlSession.getMapper(UsersMapper.class);
        }
    
        //归还SqlSession
        @After
        public void closeSession(){
            sqlSession.close();
        }
    
    
        @Test
        public void testInsertAndReturnId() throws ParseException {
            String dataStr = "1996-11-22";
            User u = new User("小青", date.parse(dataStr), "女", "沈阳市");
            int num = usersMapper.insertAndReturnId(u);
            sqlSession.commit();
            if(num == 1){
                System.out.println("导入数据成功!");
            }else{
                System.out.println("导入数据失败!");
            }
            System.out.println("用户id: " + u.getId());
        }
    }
    

    输出结果

    Checking to see if class com.example.mapper.TestUsersMapper matches criteria [is assignable to Object]
    Checking to see if class com.example.mapper.UsersMapper matches criteria [is assignable to Object]
    Opening JDBC Connection
    Created connection 295180183.
    Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@11981797]
        
    ==>  Preparing: insert into users(username, birthday, sex, address) values (?, ?, ?, ?)
    ==> Parameters: 小青(String), 1996-11-22 00:00:00.0(Timestamp), 女(String), 沈阳市(String)
    <==    Updates: 1
        
    ==>  Preparing: select last_insert_id()
    ==> Parameters: 
    <==    Columns: last_insert_id()
    <==        Row: 30
    <==      Total: 1
        
    Committing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@11981797]
        
    导入数据成功!
    用户id: 30
        
    Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@11981797]
    Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@11981797]
    Returned connection 295180183 to pool.
    
    Process finished with exit code 0
    

    测试结果分析

    • 由sql标签在底层的解析顺序以及解析后的内容可知
      • 在执行映射文件中的标签时,先执行的是selectKey标签外层标签中的sql语句,后执行的是子标签中的sql语句
    //先
    ==>  Preparing: insert into users(username, birthday, sex, address) values (?, ?, ?, ?)
    ==> Parameters: 小青(String), 1996-11-22 00:00:00.0(Timestamp), 女(String), 沈阳市(String)
    <==    Updates: 1    
    
    //后
    ==>  Preparing: select last_insert_id()
    ==> Parameters: 
    <==    Columns: last_insert_id()
    <==        Row: 30
    <==      Total: 1
    
    • 根据测试代码以及对应的输出结果可知

      • 接口文件中,方法中int类型的返回值并不是返回的用户id,而是插入操作执行后受影响的记录条数

      • keyProperty属性指明了子标签的返回结果(这里是用户id)由入参中的哪个属性来接收

    //测试代码
    
    int num = usersMapper.insertAndReturnId(u);
    sqlSession.commit();
    if(num == 1){
        System.out.println("导入数据成功!");
    }else{
        System.out.println("导入数据失败!");
    }
    System.out.println("用户id: " + u.getId());
    
    //对应输出结果
    
    导入数据成功!
        
    用户id: 30
    
    • 数据表中的结果

    image

    UUID

    • 由数字字母中划线组成的不重复的36位随机字符串
    • java和mysql对UUID都有支持
    package com.example.mapper;
    
    import java.util.UUID;
    
    public class TestUsersMapper {
    
        @Test
        public void testUUID(){
            UUID uuid = UUID.randomUUID();
            System.out.println(uuid);
        }
    }
    
    /*
    输出结果:
    c5393056-6711-46c1-8134-80b83d2e9a76
    
    Process finished with exit code 0
    */
    
    select UUID();
    
    --输出结果:13e622a2-1b0f-11ed-b2f9-0242ac110002
    
  • 相关阅读:
    java后端研发经典面试题总结六
    麓言信息 优秀的UI设计师必须了解UI设计原则
    C语言经典基础题目100题
    (一)Gluster 介绍及简单部署
    Python编辑器的选择配置和使用
    【课程作业】最优化理论与方法:第一次作业
    Springcloud之Nacos Config服务配置
    在Mac上安装和配置Node.js
    STC89C51基础及项目第10天:LCD显示字符(非标协议外设)
    qml 两个listview共用一个listmodel,显示排斥的数据
  • 原文地址:https://www.cnblogs.com/nefu-wangxun/p/16584331.html