MyBatis常用操作示例

Posted 异次猿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis常用操作示例相关的知识,希望对你有一定的参考价值。

该篇主要是Mybatis在日常开发中的使用积累,

对于Intellij IDEA 推荐一款Mybatis插件 FreeMybatis

Mybatis生成插件

mybatis-generator是一个可以生成mybatis通用代码的maven插件

插件引入

 
   
   
 
  1. <build>

  2.    <plugins>

  3.        <!-- mybatis 代码生成器插件 mybatis-generator:generate-->

  4.        <plugin>

  5.            <groupId>org.mybatis.generator</groupId>

  6.            <artifactId>mybatis-generator-maven-plugin</artifactId>

  7.            <version>1.3.2</version>

  8.            <configuration>

  9.                <verbose>true</verbose>

  10.                <overwrite>true</overwrite>

  11.            </configuration>

  12.            <dependencies>

  13.                <dependency>

  14.                    <groupId>mysql</groupId>

  15.                    <artifactId>mysql-connector-java</artifactId>

  16.                    <version>5.1.37</version>

  17.                </dependency>

  18.            </dependencies>

  19.        </plugin>

  20.    </plugins>

  21. </build>

生成命令

 
   
   
 
  1. mvn mybatis-generator:generate

配置说明

工程目录下: src/main/resources/generatorConfig.xml

 
   
   
 
  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <!DOCTYPE generatorConfiguration

  3.        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"

  4.        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

  5. <!-- 使用 mvn mybatis-generator:generate -->

  6. <generatorConfiguration>

  7.    <!-- 配置文件

  8.    <properties resource="classpath*:property/jdbc.properties" />

  9.     -->

  10.    <context id="dbTestTables" targetRuntime="MyBatis3" defaultModelType="flat">

  11.        <!-- plugin -->

  12.        <plugin type="org.mybatis.generator.plugins.SerializablePlugin" />

  13.        <!-- 是否取消生成的代码注释 true : 取消 false: 保留 -->

  14.        <commentGenerator>

  15.            <property name="suppressAllComments" value="false" />

  16.        </commentGenerator>

  17.        <!-- 连接配置 -->

  18.        <jdbcConnection driverClass="com.mysql.jdbc.Driver"

  19.                        connectionURL="jdbc:mysql://devel.mysql.com:3306/db_test?autoReconnect=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"

  20.                        userId="root"

  21.                        password="rootpwd">

  22.        </jdbcConnection>

  23.        <!-- javaModelGenerator是模型的生成信息,这里将指定这些Java model类的生成路径 -->

  24.        <javaModelGenerator targetPackage="com.tutorial.mybatis.gen.domain"

  25.                            targetProject="/Users/elonsu/IdeaProjects/examples/elonsu-batisgen-example/src/main/java">

  26.            <property name="enableSubPackages" value="true" />

  27.            <property name="trimStrings" value="true" />

  28.        </javaModelGenerator>

  29.        <!-- 生成Mapper 配置文件 -->

  30.        <sqlMapGenerator targetPackage="mapper/xml"

  31.                         targetProject="/Users/elonsu/IdeaProjects/examples/elonsu-batisgen-example/src/main/resources">

  32.            <property name="enableSubPackages" value="true" />

  33.        </sqlMapGenerator>

  34.        <!-- javaClientGenerator是应用接口的生成信息 -->

  35.        <javaClientGenerator targetPackage="com.tutorial.mybatis.gen.mapper"

  36.                             type="XMLMAPPER"

  37.                             targetProject="/Users/elonsu/IdeaProjects/examples/elonsu-batisgen-example/src/main/java">

  38.            <property name="enableSubPackages" value="true" />

  39.        </javaClientGenerator>

  40.        <!-- oracle 使用 schema 对应 用户名称空间 mysql 使用 catalog 对应 数据库, xByExample取掉生成的Example接口相关 -->

  41.        <table tableName="tb_person" domainObjectName="Person"

  42.               enableCountByExample="false"

  43.               enableDeleteByExample="false"

  44.               enableUpdateByExample="false"

  45.               selectByExampleQueryId="false"

  46.               enableSelectByExample="false">

  47.            <generatedKey column="id" sqlStatement="MySql" identity="true"/>

  48.        </table>

  49.        <table tableName="tb_order" domainObjectName="Order"

  50.               enableCountByExample="false"

  51.               enableDeleteByExample="false"

  52.               enableUpdateByExample="false"

  53.               selectByExampleQueryId="false"

  54.               enableSelectByExample="false">

  55.            <generatedKey column="id" sqlStatement="MySql" identity="true"/>

  56.        </table>

  57.    </context>

  58. </generatorConfiguration>

Mybatis常用业务SQL

示例库表

 
   
   
 
  1. CREATE TABLE `tb_test` (

  2.  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主键',

  3.  `name` varchar(64) DEFAULT NULL COMMENT '名称',

  4.  `age` bigint(20) DEFAULT '20',

  5.  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '记录建立时间',

  6.  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '记录修改时间',

  7.  PRIMARY KEY (`id`),

  8.  UNIQUE KEY `name` (`name`)

  9. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='测试表'

示例模型

 
   
   
 
  1. @Data

  2. @Builder

  3. @NoArgsConstructor

  4. @AllArgsConstructor

  5. public class TbTest implements Serializable {

  6.    private Long id;

  7.    private String name;

  8.    private Long age;

  9.    private Date createTime;

  10.    private Date updateTime;

  11. }

示例操作

插入并返回主键
接口定义
 
   
   
 
  1. public int insertFullId(TbTest tbTest);

Xml编写
 
   
   
 
  1. <insert id="insertFullId" useGeneratedKeys="true" keyProperty="id" parameterType="com.boot.stream.domain.mint.TbTest">

  2. insert into tb_test

  3. (id, name, age, create_time, update_time)

  4. values

  5. (#{id}, #{name}, #{age},#{createTime}, #{updateTime})

  6. </insert>

用例测试
 
   
   
 
  1. @Test

  2. public void insertFullId(){

  3.   Date now = new Date();

  4.   TbTest tbTest = TbTest.builder()

  5.           .age(20L).name("Elonsu").createTime(now).updateTime(now).build();

  6.   tbTestMapper.insertFullId(tbTest);

  7.   // {"age":20,"createTime":1505443787809,"id":3,"name":"Elonsu","updateTime":1505443787809}

  8.   System.out.println(JSON.toJSONString(tbTest));

  9. }

SQL执行
 
   
   
 
  1. DEBUG:2017-09-15 10:49:48.041[debug] ==>  Preparing: insert into tb_test (id, name, age, create_time, update_time) values (?, ?, ?,?, ?)

  2. DEBUG:2017-09-15 10:49:48.070[debug] ==> Parameters: null, Elonsu(String), 20(Long), 2017-09-15 10:49:47.809(Timestamp), 2017-09-15 10:49:47.809(Timestamp)

  3. DEBUG:2017-09-15 10:49:48.086[debug] <==    Updates: 1

执行结果

插入或者更新(记录存在则更新)
接口定义
 
   
   
 
  1. public void batchUpset(@Param("list") List<TbTest> list);

Xml编写
 
   
   
 
  1. <insert id="batchUpset" parameterType="java.util.Collection">

  2.    insert into tb_test

  3.      (name, age, create_time, update_time)

  4.    values

  5.    <foreach collection="list" item="li" separator=",">

  6.      <trim prefix="(" suffix=")" suffixOverrides=",">

  7.        #{li.name}, #{li.age}, #{li.createTime}, #{li.updateTime}

  8.      </trim>

  9.    </foreach>

  10.    on duplicate key update

  11.      age = values(age),

  12.      update_time = values(update_time)

  13. </insert>

用例测试
 
   
   
 
  1. @Test

  2. public void batchUpset(){

  3.   Date now = new Date();

  4.   TbTest tbTest1 = TbTest.builder()

  5.           .age(22L).name("Elonsu").createTime(now).updateTime(now).build();

  6.   TbTest tbTest2 = TbTest.builder()

  7.           .age(23L).name("Dennisit").createTime(now).updateTime(now).build();

  8.   tbTestMapper.batchUpset(Lists.newArrayList(tbTest1, tbTest2));

  9. }

SQL执行
 
   
   
 
  1. DEBUG:2017-09-15 10:54:03.623[debug] ==>  Preparing: insert into tb_test (name, age, create_time, update_time) values ( ?, ?, ?, ? ) , ( ?, ?, ?, ? ) on duplicate key update age = values(age), update_time = values(update_time)

  2. DEBUG:2017-09-15 10:54:03.680[debug] ==> Parameters: Elonsu(String), 22(Long), 2017-09-15 10:54:03.212(Timestamp), 2017-09-15 10:54:03.212(Timestamp), Dennisit(String), 23(Long), 2017-09-15 10:54:03.212(Timestamp), 2017-09-15 10:54:03.212(Timestamp)

  3. DEBUG:2017-09-15 10:54:03.721[debug] <==    Updates: 3

执行结果

MyBatis常用操作示例

批量更新(根据主键更新)
接口定义
 
   
   
 
  1. public void batchUpdate(@Param("list") List<TbTest> list);

Xml编写
 
   
   
 
  1. <update id="batchUpdate"  parameterType="java.util.Collection">

  2.    <foreach collection="list" item="li" index="index" open="" close="" separator=";">

  3.      update tb_test

  4.      <set >

  5.        <if test="li.name != null" >

  6.          name = #{li.name},

  7.        </if>

  8.        <if test="li.age != null" >

  9.          age = #{li.age},

  10.        </if>

  11.        <if test="li.createTime != null" >

  12.          create_time = #{li.createTime},

  13.        </if>

  14.        <if test="li.updateTime != null" >

  15.          update_time = #{li.updateTime},

  16.        </if>

  17.      </set>

  18.      where id = #{li.id}

  19.    </foreach>

  20. </update>

用例测试
 
   
   
 
  1. @Test

  2. public void batchUpdate(){

  3.   Date now = new Date();

  4.   TbTest tbTest1 = new TbTest(3L, "苏若年", 88L, null, now);

  5.   TbTest tbTest2 = new TbTest(4L, "墨少白", 99L, null, now);

  6.   tbTestMapper.batchUpdate(Lists.newArrayList(tbTest1, tbTest2));

  7. }

SQL执行
 
   
   
 
  1. DEBUG:2017-09-15 11:00:46.741[debug] ==>  Preparing: update tb_test SET name = ?, age = ?, update_time = ? where id = ? ; update tb_test SET name = ?, age = ?, update_time = ? where id = ?

  2. DEBUG:2017-09-15 11:00:46.776[debug] ==> Parameters: 苏若年(String), 88(Long), 2017-09-15 11:00:46.675(Timestamp), 3(Long), 墨少白(String), 99(Long), 2017-09-15 11:00:46.675(Timestamp), 4(Long)

  3. DEBUG:2017-09-15 11:00:46.797[debug] <==    Updates: 1

执行结果

MyBatis常用操作示例

批量插入
接口定义
 
   
   
 
  1. public void batchInsert(@Param("list") List<TbTest> list);

Xml编写
 
   
   
 
  1. <insert id="batchInsert" useGeneratedKeys="true" keyProperty="id" parameterType="java.util.Collection">

  2.    insert into tb_test

  3.      (name, age, create_time, update_time)

  4.    values

  5.    <foreach collection="list" item="li" index="index" separator=",">

  6.      <trim prefix="(" suffix=")" suffixOverrides=",">

  7.        #{li.name}, #{li.age}, #{li.createTime}, #{li.updateTime}

  8.      </trim>

  9.    </foreach>

  10. </insert>

用例测试
 
   
   
 
  1. @Test

  2. public void batchInsert(){

  3.   Date now = new Date();

  4.   TbTest tbTest1 = TbTest.builder()

  5.           .age(66L).name("mock1").createTime(now).updateTime(now).build();

  6.   TbTest tbTest2 = TbTest.builder()

  7.           .age(77L).name("mock2").createTime(now).updateTime(now).build();

  8.   tbTestMapper.batchInsert(Lists.newArrayList(tbTest1, tbTest2));

  9.   // tbTest1: {"age":66,"createTime":1505445581768,"id":8,"name":"mock1","updateTime":1505445581768}

  10.   System.out.println("tbTest1: " + JSON.toJSONString(tbTest1));

  11.   // tbTest2: {"age":77,"createTime":1505445581768,"id":9,"name":"mock2","updateTime":1505445581768}

  12.   System.out.println("tbTest2: " + JSON.toJSONString(tbTest2));

  13. }

SQL执行
 
   
   
 
  1. DEBUG:2017-09-15 11:19:41.823[debug] ==>  Preparing: insert into tb_test (name, age, create_time, update_time) values ( ?, ?, ?, ? ) , ( ?, ?, ?, ? )  

  2. DEBUG:2017-09-15 11:19:41.862[debug] ==> Parameters: mock1(String), 66(Long), 2017-09-15 11:19:41.768(Timestamp), 2017-09-15 11:19:41.768(Timestamp), mock2(String), 77(Long), 2017-09-15 11:19:41.768(Timestamp), 2017-09-15 11:19:41.768(Timestamp)

  3. DEBUG:2017-09-15 11:19:41.882[debug] <==    Updates: 2

执行结果

动态表/字段传递
接口定义
 
   
   
 
  1. public TbTest columnDynamic(@Param("column") String column, @Param("val") String s);

Xml编写
 
   
   
 
  1. <select id="columnDynamic" resultType="com.boot.stream.domain.mint.TbTest">

  2.    select ${column} from tb_test where ${column} = #{val}

  3. </select>

用例测试
 
   
   
 
  1. @Test

  2. public void dynamicColumn(){

  3.   // {"name":"苏若年"}

  4.   System.out.println(JSON.toJSONString(tbTestMapper.columnDynamic("name", "苏若年")));

  5.   // {"age":99}

  6.   System.out.println(JSON.toJSONString(tbTestMapper.columnDynamic("age", "99")));

  7. }

SQL执行
 
   
   
 
  1. DEBUG:2017-09-15 11:39:10.585[debug] ==>  Preparing: select name from tb_test where name = ?  

  2. DEBUG:2017-09-15 11:39:10.619[debug] ==> Parameters: 苏若年(String)

  3. DEBUG:2017-09-15 11:39:10.656[debug] <==      Total: 1

  4. DEBUG:2017-09-15 11:39:10.675[debug] ==>  Preparing: select age from tb_test where age = ?  

  5. DEBUG:2017-09-15 11:39:10.675[debug] ==> Parameters: 99(String)

  6. DEBUG:2017-09-15 11:39:10.686[debug] <==      Total: 1

说明: 在动态sql解析过程, #{}${}的效果是不一样的

  • #{}将传入的参数当成一个字符串,会给传入的参数加一个双引号

  • ${}将传入的参数直接显示生成在sql中,不会添加引号

  • #{}能够很大程度上防止sql注入, ${}无法防止sql注入

  • ${}在预编译之前已经被变量替换了,这会存在sql注入的风险

接下来展示一个sql注入的示例

接口定义
 
   
   
 
  1. public List<TbTest> tableDynamic(@Param("tableName") String tableName);

Xml编写
 
   
   
 
  1. <select id="tableDynamic" resultType="com.boot.stream.domain.mint.TbTest" statementType="STATEMENT">

  2.    select * from ${tableName} where 1=1

  3. </select>

用例测试
 
   
   
 
  1. @Test

  2. public void sqlInject(){

  3.   // [{"age":88,"id":3,"name":"苏若年"},{"age":99,"id":4,"name":"墨少白"},{"age":66,"id":8,"name":"mock1"},{"age":77,"id":9,"name":"mock2"}]

  4.   System.out.println(JSON.toJSONString(tbTestMapper.tableDynamic("tb_test; delete from tb_test; --")));

  5.   // []

  6.   System.out.println(JSON.toJSONString(tbTestMapper.tableDynamic("tb_test")));

  7. }

SQL执行
 
   
   
 
  1. DEBUG:2017-09-15 12:06:49.867[debug] ==>  Preparing: select * from tb_test; delete from tb_test; -- where 1=1

  2. DEBUG:2017-09-15 12:06:49.868[debug] ==> Parameters:

  3. DEBUG:2017-09-15 12:06:49.876[debug] <==      Total: 4

  4. DEBUG:2017-09-15 12:06:49.876[debug] <==    Updates: 4

  5. DEBUG:2017-09-15 12:06:49.878[debug] ==>  Preparing: select * from tb_test where 1=1

  6. DEBUG:2017-09-15 12:06:49.879[debug] ==> Parameters:

  7. DEBUG:2017-09-15 12:06:49.882[debug] <==      Total: 0

可以看到,因为SQL注入,导致表中所有数据被清除.

批量主键查询
接口定义
 
   
   
 
  1. public List<TbTest> selectByIds(@Param("list") List<Long> ids);

Xml编写
 
   
   
 
  1. <select id="selectByIds" resultType="com.boot.stream.domain.mint.TbTest">

  2.    SELECT

  3.     <include refid="sqlColumnList"/>

  4.    FROM

  5.     tb_test

  6.    where id IN

  7.    <foreach collection="list" item="li" open="(" separator="," close=")">

  8.     #{li}

  9.    </foreach>

  10. </select>

用例测试
 
   
   
 
  1. @Test

  2. public void selectByIds(){

  3.   // [{"age":88,"createTime":1505455272000,"id":10,"name":"苏若年","updateTime":1505455274000},{"age":99,"createTime":1505455272000,"id":11,"name":"墨少白","updateTime":1505455274000},{"age":99,"createTime":1505455272000,"id":12,"name":"林允儿","updateTime":1505455274000}]

  4.   System.out.println(JSON.toJSONString(tbTestMapper.selectByIds(Lists.newArrayList(10L, 11L, 12L))));

  5. }

SQL执行
 
   
   
 
  1. EBUG:2017-09-15 14:15:32.061[debug] ==>  Preparing: SELECT id AS id, name AS name, age AS age, create_time AS createTime, update_time AS updateTime FROM tb_test where id IN ( ? , ? , ? )  

  2. DEBUG:2017-09-15 14:15:32.089[debug] ==> Parameters: 10(Long), 11(Long), 12(Long)

  3. DEBUG:2017-09-15 14:15:32.123[debug] <==      Total: 3

动态条件查询
接口定义
 
   
   
 
  1. public List<TbTest> selectByCondition(@Param("object") TbTest tbTest);

Xml编写
 
   
   
 
  1. <!-- 根据条件查询 -->

  2. <select id="selectByCondition" resultType="com.boot.stream.domain.mint.TbTest">

  3. SELECT

  4. <include refid="sqlColumnList"/>

  5. FROM

  6. tb_test

  7. <include refid="sqlQueryCondition"/>

  8. <include refid="sqlSortByList"/>

  9. </select>

  10. <!-- 表字段集 -->

  11. <sql id="sqlColumnList">

  12. <trim suffixOverrides=",">

  13. id AS id, name AS name, age AS age, create_time AS createTime, update_time AS updateTime,

  14. </trim>

  15. </sql>

  16. <!-- 查询条件 -->

  17. <sql id="sqlQueryCondition">

  18. <trim suffixOverrides="," prefixOverrides="AND|OR">

  19. <where>

  20.   <choose>

  21.     <when test="object.id > 0">

  22.       id = #{object.id}

  23.     </when>

  24.     <otherwise>

  25.       <if test="object.name != null">

  26.         AND name = #{object.name}

  27.       </if>

  28.       <if test="object.age != null">

  29.         AND age = #{object.age}

  30.       </if>

  31.       <if test="object.createTime">

  32.         AND create_time = #{object.createTime}

  33.       </if>

  34.       <if test="object.updateTime">

  35.         AND update_time = #{object.updateTime}

  36.       </if>

  37.     </otherwise>

  38.   </choose>

  39. </where>

  40. </trim>

  41. </sql>

  42. <!-- 结果集排序集合 -->

  43. <sql id="sqlSortByList">

  44. ORDER BY

  45. <trim suffixOverrides=",">

  46. id DESC, update_time DESC, create_time DESC, age DESC,

  47. </trim>

  48. </sql>

用例测试
 
   
   
 
  1. @Test

  2. public void selectByCondition(){

  3.   // 条件含主键查询:[{"age":88,"createTime":1505455272000,"id":10,"name":"苏若年","updateTime":1505455274000}]

  4.   System.out.println("条件含主键查询:" + JSON.toJSONString(tbTestMapper.selectByCondition(TbTest.builder().id(10L).build())));

  5.   // 条件非主键查询:[{"age":99,"createTime":1505455272000,"id":12,"name":"林允儿","updateTime":1505455274000},{"age":99,"createTime":1505455272000,"id":11,"name":"墨少白","updateTime":1505455274000}]

  6.   System.out.println("条件非主键查询:" + JSON.toJSONString(tbTestMapper.selectByCondition(TbTest.builder().age(99L).build())));

  7. }

SQL执行
 
   
   
 
  1. DEBUG:2017-09-15 14:18:26.630[debug] ==>  Preparing: SELECT id AS id, name AS name, age AS age, create_time AS createTime, update_time AS updateTime FROM tb_test WHERE id = ? ORDER BY id DESC, update_time DESC, create_time DESC, age DESC  

  2. DEBUG:2017-09-15 14:18:26.659[debug] ==> Parameters: 10(Long)

  3. DEBUG:2017-09-15 14:18:26.700[debug] <==      Total: 1

  4. DEBUG:2017-09-15 14:18:26.723[debug] ==>  Preparing: SELECT id AS id, name AS name, age AS age, create_time AS createTime, update_time AS updateTime FROM tb_test WHERE age = ? ORDER BY id DESC, update_time DESC, create_time DESC, age DESC  

  5. DEBUG:2017-09-15 14:18:26.723[debug] ==> Parameters: 99(Long)

  6. DEBUG:2017-09-15 14:18:26.727[debug] <==      Total: 2





点击下方二维码, 关注【异次猿】



以上是关于MyBatis常用操作示例的主要内容,如果未能解决你的问题,请参考以下文章

Mybatis:Mybatis注解开发单表操作(代码实例)

Mybatis动态sql技术

提效小技巧——记录那些不常用的代码片段

MybatisPlus对比Mybatis有哪些优势?

Mybatis -- 动态Sql概述动态Sql之<if>(包含<where>)动态Sql之<foreach>sql片段抽取

C#程序员经常用到的10个实用代码片段 - 操作系统