MyBatis-04 MyBatis XML方式之insert元素

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: MyBatis-04 MyBatis XML方式之insert元素

insert概述


MyBatis-03 MyBatis XML方式之select元素比起来,insert要简单的多。 只有让它返回主键值时,由于不同的数据库的主键生成方式不同,这种情况会复杂一点。


简单的insert用法

1. UserMapper中添加接口方法

    /**
     * 
     * 
     * @Title: insertSysUser
     * 
     * @Description: 增加SysUser
     * 
     * @param sysUser
     * @return
     * 
     * @return: int 受影响的行数
     */
    int insertSysUser(SysUser sysUser);


2. UserMapper.xml 添加节点

<!-- 添加SysUser -->
    <insert id="insertSysUser" >
        insert into sys_user(
            id,user_name, user_password, user_email, 
            user_info, head_img, create_time)
        values(
            #{id},#{userName}, #{userPassword}, #{userEmail}, 
            #{userInfo}, #{headImg, jdbcType=BLOB}, #{createTime, jdbcType=TIMESTAMP})
    </insert>


先看下insert元素标签包含的属性


20180416064226246.png


id:命名空间中的唯一标示符


parameterType:传入的语句参数的全限定类名或者别名,因为 MyBatis可以推断传入语句的具体参数,因此不建议配置该属性


flushCache :默认true,任何时候只要语句被调用,都会清空一级缓存和二级缓存


timeout:设置在抛出异常之前,驱动程序等待数据库返回请求结果的秒数


statementType : 默认PREPARED


useGenerateKeys: 默认false. 如果设置为true , MyBatis会使用JDBC的getGeneratedKeys方法取出由数据库内部生成的主键


keyProperty: MyBatis通过getGeneratedKeys获取组建后要将辅助的属性名。


keyColumn:仅对UPDATE和INSERT又有,通过生成的键值设置表中的列名。


databaseId:如果配置了databaseIdProvider, MyBatis会加载所有的不带databaseId或者匹配当前databaseId的语句。 如果同时存在带databaseId和不带databaseId的语句,后者将被忽略。


此外,insert中的sql语句就是一个简单的insert语句,将所有的列都列举出来,在value中通过#{property}方式从参数中取出属性的值。


为了防止类型错误,对于一些特殊的数据类型,建议指定具体的jdbcType值#{headImg, jdbcType=BLOB}, #{createTime, jdbcType=TIMESTAMP}


3. 编写单元测试

@Test
    public void insertSysUserTest() {
        logger.info("insertSysUserTest");
        // 获取SqlSession
        SqlSession sqlSession = getSqlSession();
        try {
            // 获取UserMapper接口
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            SysUser sysUser = new SysUser();
            sysUser.setUserName("artisanTest");
            sysUser.setUserPassword("123456");
            sysUser.setUserEmail("test@artisan.com");
            sysUser.setUserInfo("测试用户");
            // 模拟头像
            sysUser.setHeadImg(new byte[] { 1, 2, 3 });
            sysUser.setCreateTime(new Date());
            // 新增用户 ,返回受影响的行数
            int result = userMapper.insertSysUser(sysUser);
            // 只插入一条数据 ,期望是1
            Assert.assertEquals(1, result);
            // id 为null , 因为没有给ID赋值,也没有配置回写id的值 ,期望是null
            Assert.assertNull(sysUser.getId());
            logger.info("受影响的行数:" + result);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 为了保持测试数据的干净,这里选择回滚
            // 由于默认的sqlSessionFactory.openSession()是不自动提交的
            // 除非显式的commit,否则不会提交到数据库
            sqlSession.rollback();
            logger.info("为了保持测试数据的干净,这里选择回滚,不写入mysql,请观察日志,回滚完成");
            sqlSession.close();
            logger.info("sqlSession close successfully ");
        }
    }


日志

2018-04-15 18:32:49,378  INFO [main] (BaseMapperTest.java:26) - sessionFactory bulit successfully
2018-04-15 18:32:49,383  INFO [main] (BaseMapperTest.java:29) - reader close successfully
2018-04-15 18:32:49,386  INFO [main] (UserMapperTest.java:152) - insertSysUserTest
2018-04-15 18:32:49,970 DEBUG [main] (BaseJdbcLogger.java:142) - ==>  Preparing: insert into sys_user( id,user_name, user_password, user_email, user_info, head_img, create_time) values( ?,?, ?, ?, ?, ?, ?) 
2018-04-15 18:32:50,060 DEBUG [main] (BaseJdbcLogger.java:142) - ==> Parameters: null, artisanTest(String), 123456(String), test@artisan.com(String), 测试用户(String), java.io.ByteArrayInputStream@50a14c18(ByteArrayInputStream), 2018-04-15 18:32:49.403(Timestamp)
2018-04-15 18:32:50,066 DEBUG [main] (BaseJdbcLogger.java:142) - <==    Updates: 1
2018-04-15 18:32:50,067  INFO [main] (UserMapperTest.java:174) - 受影响的行数:1
2018-04-15 18:32:50,078  INFO [main] (UserMapperTest.java:182) - 为了保持测试数据的干净,这里选择回滚,不写入mysql,请观察日志,回滚完成
2018-04-15 18:32:50,080  INFO [main] (UserMapperTest.java:185) - sqlSession close successfully 


使用JDCB方式返回主键自增的值


在使用主键自增(比如MySql 、SQLServer数据库)时,插入数据库后可以需要得到自增的主键值,然后使用这个值进行一些其他的操作。


1.UserMapper接口增加接口方法

// 演示使用JDBC方式返回主键的自增长值
int insertSysUser2(SysUser sysUser);


2.UserMapper.xml 配置

    <!-- 添加SysUser 使用JDBC的方式返回自增长的主键的值-->
    <insert id="insertSysUser2"  useGeneratedKeys="true" keyProperty="id">
        insert into sys_user(
            user_name, user_password, user_email, 
            user_info, head_img, create_time)
        values(
            #{userName}, #{userPassword}, #{userEmail}, 
            #{userInfo}, #{headImg, jdbcType=BLOB}, #{createTime, jdbcType=TIMESTAMP})
    </insert>


和insertSysUser比较, insertSysUser2主要的变化是在insert 标签上配置了两个属性

useGeneratedKeys="true" keyProperty="id"


useGeneratedKeys设置为true后, MyBatis会使用JDBC的getGeneratedKeys方法来取由数据库内部生成的主键。 获取主键值后将其赋值给keyProperty配置的id属性。


当需要设置多个属性时,使用逗号分开,这种情况下通常还需要设置keyColunm属性,按顺序指定数据库的列,这里的列的值会和keyProperty配置的属性一一对应。


由于使用数据库返回的主键值,所以SQL上线两部分中的列去掉了id列和对应的#{id}属性。


3.单元测试

@Test
    public void insertSysUser2Test() {
        logger.info("insertSysUser2Test");
        // 获取SqlSession
        SqlSession sqlSession = getSqlSession();
        try {
            // 获取UserMapper接口
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            SysUser sysUser = new SysUser();
            sysUser.setUserName("artisanTest");
            sysUser.setUserPassword("123456");
            sysUser.setUserEmail("test@artisan.com");
            sysUser.setUserInfo("测试用户");
            // 模拟头像
            sysUser.setHeadImg(new byte[] { 1, 2, 3 });
            sysUser.setCreateTime(new Date());
            // 新增用户 ,返回受影响的行数
            int result = userMapper.insertSysUser2(sysUser);
            // 只插入一条数据 ,期望是1
            Assert.assertEquals(1, result);
            // id不为null ,因为使用了 useGeneratedKeys="true" keyProperty="id"
            Assert.assertNotNull(sysUser.getId());
            logger.info("受影响的行数:" + result);
            logger.info("userId:" + sysUser.getId());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 为了保持测试数据的干净,这里选择回滚
            // 由于默认的sqlSessionFactory.openSession()是不自动提交的
            // 除非显式的commit,否则不会提交到数据库
            sqlSession.rollback();
            logger.info("为了保持测试数据的干净,这里选择回滚,不写入mysql,请观察日志,回滚完成");
            sqlSession.close();
            logger.info("sqlSession close successfully ");
        }
    }


日志

2018-04-16 00:36:27,508  INFO [main] (BaseMapperTest.java:26) - sessionFactory bulit successfully
2018-04-16 00:36:27,511  INFO [main] (BaseMapperTest.java:29) - reader close successfully
2018-04-16 00:36:27,514  INFO [main] (UserMapperTest.java:191) - insertSysUser2Test
2018-04-16 00:36:28,049 DEBUG [main] (BaseJdbcLogger.java:142) - ==>  Preparing: insert into sys_user( user_name, user_password, user_email, user_info, head_img, create_time) values( ?, ?, ?, ?, ?, ?) 
2018-04-16 00:36:28,112 DEBUG [main] (BaseJdbcLogger.java:142) - ==> Parameters: artisanTest(String), 123456(String), test@artisan.com(String), 测试用户(String), java.io.ByteArrayInputStream@4021065(ByteArrayInputStream), 2018-04-16 00:36:27.526(Timestamp)
2018-04-16 00:36:28,124 DEBUG [main] (BaseJdbcLogger.java:142) - <==    Updates: 1
2018-04-16 00:36:28,125  INFO [main] (UserMapperTest.java:213) - 受影响的行数:1
2018-04-16 00:36:28,125  INFO [main] (UserMapperTest.java:214) - userId:1002
2018-04-16 00:36:28,127  INFO [main] (UserMapperTest.java:222) - 为了保持测试数据的干净,这里选择回滚,不写入mysql,请观察日志,回滚完成
2018-04-16 00:36:28,129  INFO [main] (UserMapperTest.java:225) - sqlSession close successfully 


使用selectKey返回主键的值


上面这种写法只适用于支持组件自增的数据库,有些数据库比如Oracle不提供主键自增的功能,而是使用序列得到一个值,然后将这个值赋给id ,然后再插入数据库。


对应这种情况,可以使用 selectKey标签来获取主键的值,这种方式不仅使用不提供主键自增功能的数据库,同时也适用于提供主键自增功能的数据库


1.UserMapper接口增加接口方法

// 演示使用selectKey的方式返回主键的自增长值
int insertSysUser3(SysUser sysUser);


2.UserMapper.xml 配置

    <!-- 添加SysUser 使用selectKey的方式返回自增长的主键的值-->
    <insert id="insertSysUser3">
        insert into sys_user(
            user_name, user_password, user_email, 
            user_info, head_img, create_time)
        values(
            #{userName}, #{userPassword}, #{userEmail}, 
            #{userInfo}, #{headImg, jdbcType=BLOB}, #{createTime, jdbcType=TIMESTAMP})
        <selectKey keyColumn="id" resultType="long" keyProperty="id"  order="AFTER">
            select last_insert_id()
        </selectKey>
    </insert>


  • selectKey标签的keyColum、keyProperty
    和上面useGeneratedKeys的用法含义相同。
  • resultType用于设置返回值的类型。
  • order属性的设置和数据库有关。


Mysql中,order属性设置为AFTER。因为当前记录的主键值是在insert语句执行成功后才获取到的。

Oracle数据库中,order的值设置为BEFORE,这是因为ORCLE数据库需要先从序列中获取中,然后将值作为主键插入数据库中


ORACLE的写法如下

<insert  id="insertUser" >
<selectKey resultType="java.lang.Integer" order="BEFORE" 
keyProperty="id">
    SELECT 自定义序列.NEXTVAL FROM DUAL
</selectKey>
insert into *******
</insert>
注意这里使用的order是“BEFORE”


3.单元测试

    @Test
    public void insertSysUser3Test() {
        logger.info("insertSysUser3Test");
        // 获取SqlSession
        SqlSession sqlSession = getSqlSession();
        try {
            // 获取UserMapper接口
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            SysUser sysUser = new SysUser();
            sysUser.setUserName("artisanTest");
            sysUser.setUserPassword("123456");
            sysUser.setUserEmail("test@artisan.com");
            sysUser.setUserInfo("测试用户");
            // 模拟头像
            sysUser.setHeadImg(new byte[] { 1, 2, 3 });
            sysUser.setCreateTime(new Date());
            // 新增用户 ,返回受影响的行数
            int result = userMapper.insertSysUser3(sysUser);
            // 只插入一条数据 ,期望是1
            Assert.assertEquals(1, result);
            // id不为null ,因为使用了 useGeneratedKeys="true" keyProperty="id"
            Assert.assertNotNull(sysUser.getId());
            logger.info("受影响的行数:" + result);
            logger.info("userId:" + sysUser.getId());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 为了保持测试数据的干净,这里选择回滚
            // 由于默认的sqlSessionFactory.openSession()是不自动提交的
            // 除非显式的commit,否则不会提交到数据库
            sqlSession.rollback();
            logger.info("为了保持测试数据的干净,这里选择回滚,不写入mysql,请观察日志,回滚完成");
            sqlSession.close();
            logger.info("sqlSession close successfully ");
        }
    }


日志

2018-04-16 00:44:17,807  INFO [main] (BaseMapperTest.java:26) - sessionFactory bulit successfully
2018-04-16 00:44:17,811  INFO [main] (BaseMapperTest.java:29) - reader close successfully
2018-04-16 00:44:17,814  INFO [main] (UserMapperTest.java:231) - insertSysUser3Test
2018-04-16 00:44:18,278 DEBUG [main] (BaseJdbcLogger.java:142) - ==>  Preparing: insert into sys_user( user_name, user_password, user_email, user_info, head_img, create_time) values( ?, ?, ?, ?, ?, ?) 
2018-04-16 00:44:18,353 DEBUG [main] (BaseJdbcLogger.java:142) - ==> Parameters: artisanTest(String), 123456(String), test@artisan.com(String), 测试用户(String), java.io.ByteArrayInputStream@18a52c57(ByteArrayInputStream), 2018-04-16 00:44:17.833(Timestamp)
2018-04-16 00:44:18,359 DEBUG [main] (BaseJdbcLogger.java:142) - <==    Updates: 1
2018-04-16 00:44:18,361 DEBUG [main] (BaseJdbcLogger.java:142) - ==>  Preparing: select last_insert_id() 
2018-04-16 00:44:18,362 DEBUG [main] (BaseJdbcLogger.java:142) - ==> Parameters: 
2018-04-16 00:44:18,386 TRACE [main] (BaseJdbcLogger.java:148) - <==    Columns: last_insert_id()
2018-04-16 00:44:18,386 TRACE [main] (BaseJdbcLogger.java:148) - <==        Row: 1003
2018-04-16 00:44:18,389 DEBUG [main] (BaseJdbcLogger.java:142) - <==      Total: 1
2018-04-16 00:44:18,391  INFO [main] (UserMapperTest.java:253) - 受影响的行数:1
2018-04-16 00:44:18,391  INFO [main] (UserMapperTest.java:254) - userId:1003
2018-04-16 00:44:18,396  INFO [main] (UserMapperTest.java:262) - 为了保持测试数据的干净,这里选择回滚,不写入mysql,请观察日志,回滚完成
2018-04-16 00:44:18,398  INFO [main] (UserMapperTest.java:265) - sqlSession close successfully 


Mysql使用 uuid实现主键

需要增加通过select uuid()得到uuid值

<insert  id="insertUser">
    <selectKey resultType="java.lang.String" order="BEFORE" 
        keyProperty="id">
    select uuid()
    </selectKey>
    insert into sys_user(
                user_name, user_password, user_email, 
                user_info, head_img, create_time)
            values(
                #{userName}, #{userPassword}, #{userEmail}, 
                #{userInfo}, #{headImg, jdbcType=BLOB}, #{createTime, jdbcType=TIMESTAMP})
</insert>


注意这里使用的order是“BEFORE” , 比较简单就不再测试了。


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
13天前
|
SQL 缓存 Java
MyBatis如何关闭一级缓存(分注解和xml两种方式)
MyBatis如何关闭一级缓存(分注解和xml两种方式)
42 5
|
1月前
|
XML 数据库 数据格式
|
1月前
|
SQL Java 数据库连接
Mybatis的<insert>,<update>,<delete>标签用法
这篇文章详细讲解了Mybatis中<insert>, <update>, <delete>标签的使用方法,并提供了示例代码来展示如何执行数据库的增删改操作。
29 0
|
2月前
|
SQL XML Java
mybatis :sqlmapconfig.xml配置 ++++Mapper XML 文件(sql/insert/delete/update/select)(增删改查)用法
当然,这些仅是MyBatis功能的初步介绍。MyBatis还提供了高级特性,如动态SQL、类型处理器、插件等,可以进一步提供对数据库交互的强大支持和灵活性。希望上述内容对您理解MyBatis的基本操作有所帮助。在实际使用中,您可能还需要根据具体的业务要求调整和优化SQL语句和配置。
44 1
|
3月前
|
XML 存储 数据库
XML 中的元素和属性
【8月更文挑战第22天】
54 0
|
3月前
|
SQL Java 数据库连接
MyBatis Mapper.XML 标签使用说明
MyBatis Mapper.XML 标签使用说明
38 0
|
4月前
|
XML Java 数据格式
支付系统----微信支付20---创建案例项目--集成Mybatis-plus的补充,target下只有接口的编译文件,xml文件了,添加日志的写法
支付系统----微信支付20---创建案例项目--集成Mybatis-plus的补充,target下只有接口的编译文件,xml文件了,添加日志的写法
|
5月前
|
XML 关系型数据库 数据库
使用mybatis-generator插件生成postgresql数据库model、mapper、xml
使用mybatis-generator插件生成postgresql数据库model、mapper、xml
501 0
|
1月前
|
XML 前端开发 Java
讲解SSM的xml文件
本文详细介绍了SSM框架中的xml配置文件,包括springMVC.xml和applicationContext.xml,涉及组件扫描、数据源配置、事务管理、MyBatis集成以及Spring MVC的视图解析器配置。
57 1
|
3月前
|
XML Java 数据格式
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
这篇文章是Spring5框架的实战教程,主要介绍了如何在Spring的IOC容器中通过XML配置方式使用外部属性文件来管理Bean,特别是数据库连接池的配置。文章详细讲解了创建属性文件、引入属性文件到Spring配置、以及如何使用属性占位符来引用属性文件中的值。
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)