MyBatis常用操作示例
Posted 异次猿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis常用操作示例相关的知识,希望对你有一定的参考价值。
该篇主要是Mybatis在日常开发中的使用积累,
对于Intellij IDEA 推荐一款Mybatis插件 FreeMybatis
Mybatis生成插件
mybatis-generator是一个可以生成mybatis通用代码的maven插件
插件引入
<build>
<plugins>
<!-- mybatis 代码生成器插件 mybatis-generator:generate-->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
生成命令
mvn mybatis-generator:generate
配置说明
工程目录下: src/main/resources/generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<!-- 使用 mvn mybatis-generator:generate -->
<generatorConfiguration>
<!-- 配置文件
<properties resource="classpath*:property/jdbc.properties" />
-->
<context id="dbTestTables" targetRuntime="MyBatis3" defaultModelType="flat">
<!-- plugin -->
<plugin type="org.mybatis.generator.plugins.SerializablePlugin" />
<!-- 是否取消生成的代码注释 true : 取消 false: 保留 -->
<commentGenerator>
<property name="suppressAllComments" value="false" />
</commentGenerator>
<!-- 连接配置 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://devel.mysql.com:3306/db_test?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8"
userId="root"
password="rootpwd">
</jdbcConnection>
<!-- javaModelGenerator是模型的生成信息,这里将指定这些Java model类的生成路径 -->
<javaModelGenerator targetPackage="com.tutorial.mybatis.gen.domain"
targetProject="/Users/elonsu/IdeaProjects/examples/elonsu-batisgen-example/src/main/java">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- 生成Mapper 配置文件 -->
<sqlMapGenerator targetPackage="mapper/xml"
targetProject="/Users/elonsu/IdeaProjects/examples/elonsu-batisgen-example/src/main/resources">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!-- javaClientGenerator是应用接口的生成信息 -->
<javaClientGenerator targetPackage="com.tutorial.mybatis.gen.mapper"
type="XMLMAPPER"
targetProject="/Users/elonsu/IdeaProjects/examples/elonsu-batisgen-example/src/main/java">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!-- oracle 使用 schema 对应 用户名称空间 mysql 使用 catalog 对应 数据库, xByExample取掉生成的Example接口相关 -->
<table tableName="tb_person" domainObjectName="Person"
enableCountByExample="false"
enableDeleteByExample="false"
enableUpdateByExample="false"
selectByExampleQueryId="false"
enableSelectByExample="false">
<generatedKey column="id" sqlStatement="MySql" identity="true"/>
</table>
<table tableName="tb_order" domainObjectName="Order"
enableCountByExample="false"
enableDeleteByExample="false"
enableUpdateByExample="false"
selectByExampleQueryId="false"
enableSelectByExample="false">
<generatedKey column="id" sqlStatement="MySql" identity="true"/>
</table>
</context>
</generatorConfiguration>
Mybatis常用业务SQL
示例库表
CREATE TABLE `tb_test` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`name` varchar(64) DEFAULT NULL COMMENT '名称',
`age` bigint(20) DEFAULT '20',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '记录建立时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '记录修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='测试表'
示例模型
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TbTest implements Serializable {
private Long id;
private String name;
private Long age;
private Date createTime;
private Date updateTime;
}
示例操作
插入并返回主键
接口定义
public int insertFullId(TbTest tbTest);
Xml编写
<insert id="insertFullId" useGeneratedKeys="true" keyProperty="id" parameterType="com.boot.stream.domain.mint.TbTest">
insert into tb_test
(id, name, age, create_time, update_time)
values
(#{id}, #{name}, #{age},#{createTime}, #{updateTime})
</insert>
用例测试
@Test
public void insertFullId(){
Date now = new Date();
TbTest tbTest = TbTest.builder()
.age(20L).name("Elonsu").createTime(now).updateTime(now).build();
tbTestMapper.insertFullId(tbTest);
// {"age":20,"createTime":1505443787809,"id":3,"name":"Elonsu","updateTime":1505443787809}
System.out.println(JSON.toJSONString(tbTest));
}
SQL执行
DEBUG:2017-09-15 10:49:48.041[debug] ==> Preparing: insert into tb_test (id, name, age, create_time, update_time) values (?, ?, ?,?, ?)
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)
DEBUG:2017-09-15 10:49:48.086[debug] <== Updates: 1
执行结果
插入或者更新(记录存在则更新)
接口定义
public void batchUpset(@Param("list") List<TbTest> list);
Xml编写
<insert id="batchUpset" parameterType="java.util.Collection">
insert into tb_test
(name, age, create_time, update_time)
values
<foreach collection="list" item="li" separator=",">
<trim prefix="(" suffix=")" suffixOverrides=",">
#{li.name}, #{li.age}, #{li.createTime}, #{li.updateTime}
</trim>
</foreach>
on duplicate key update
age = values(age),
update_time = values(update_time)
</insert>
用例测试
@Test
public void batchUpset(){
Date now = new Date();
TbTest tbTest1 = TbTest.builder()
.age(22L).name("Elonsu").createTime(now).updateTime(now).build();
TbTest tbTest2 = TbTest.builder()
.age(23L).name("Dennisit").createTime(now).updateTime(now).build();
tbTestMapper.batchUpset(Lists.newArrayList(tbTest1, tbTest2));
}
SQL执行
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)
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)
DEBUG:2017-09-15 10:54:03.721[debug] <== Updates: 3
执行结果
批量更新(根据主键更新)
接口定义
public void batchUpdate(@Param("list") List<TbTest> list);
Xml编写
<update id="batchUpdate" parameterType="java.util.Collection">
<foreach collection="list" item="li" index="index" open="" close="" separator=";">
update tb_test
<set >
<if test="li.name != null" >
name = #{li.name},
</if>
<if test="li.age != null" >
age = #{li.age},
</if>
<if test="li.createTime != null" >
create_time = #{li.createTime},
</if>
<if test="li.updateTime != null" >
update_time = #{li.updateTime},
</if>
</set>
where id = #{li.id}
</foreach>
</update>
用例测试
@Test
public void batchUpdate(){
Date now = new Date();
TbTest tbTest1 = new TbTest(3L, "苏若年", 88L, null, now);
TbTest tbTest2 = new TbTest(4L, "墨少白", 99L, null, now);
tbTestMapper.batchUpdate(Lists.newArrayList(tbTest1, tbTest2));
}
SQL执行
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 = ?
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)
DEBUG:2017-09-15 11:00:46.797[debug] <== Updates: 1
执行结果
批量插入
接口定义
public void batchInsert(@Param("list") List<TbTest> list);
Xml编写
<insert id="batchInsert" useGeneratedKeys="true" keyProperty="id" parameterType="java.util.Collection">
insert into tb_test
(name, age, create_time, update_time)
values
<foreach collection="list" item="li" index="index" separator=",">
<trim prefix="(" suffix=")" suffixOverrides=",">
#{li.name}, #{li.age}, #{li.createTime}, #{li.updateTime}
</trim>
</foreach>
</insert>
用例测试
@Test
public void batchInsert(){
Date now = new Date();
TbTest tbTest1 = TbTest.builder()
.age(66L).name("mock1").createTime(now).updateTime(now).build();
TbTest tbTest2 = TbTest.builder()
.age(77L).name("mock2").createTime(now).updateTime(now).build();
tbTestMapper.batchInsert(Lists.newArrayList(tbTest1, tbTest2));
// tbTest1: {"age":66,"createTime":1505445581768,"id":8,"name":"mock1","updateTime":1505445581768}
System.out.println("tbTest1: " + JSON.toJSONString(tbTest1));
// tbTest2: {"age":77,"createTime":1505445581768,"id":9,"name":"mock2","updateTime":1505445581768}
System.out.println("tbTest2: " + JSON.toJSONString(tbTest2));
}
SQL执行
DEBUG:2017-09-15 11:19:41.823[debug] ==> Preparing: insert into tb_test (name, age, create_time, update_time) values ( ?, ?, ?, ? ) , ( ?, ?, ?, ? )
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)
DEBUG:2017-09-15 11:19:41.882[debug] <== Updates: 2
执行结果
动态表/字段传递
接口定义
public TbTest columnDynamic(@Param("column") String column, @Param("val") String s);
Xml编写
<select id="columnDynamic" resultType="com.boot.stream.domain.mint.TbTest">
select ${column} from tb_test where ${column} = #{val}
</select>
用例测试
@Test
public void dynamicColumn(){
// {"name":"苏若年"}
System.out.println(JSON.toJSONString(tbTestMapper.columnDynamic("name", "苏若年")));
// {"age":99}
System.out.println(JSON.toJSONString(tbTestMapper.columnDynamic("age", "99")));
}
SQL执行
DEBUG:2017-09-15 11:39:10.585[debug] ==> Preparing: select name from tb_test where name = ?
DEBUG:2017-09-15 11:39:10.619[debug] ==> Parameters: 苏若年(String)
DEBUG:2017-09-15 11:39:10.656[debug] <== Total: 1
DEBUG:2017-09-15 11:39:10.675[debug] ==> Preparing: select age from tb_test where age = ?
DEBUG:2017-09-15 11:39:10.675[debug] ==> Parameters: 99(String)
DEBUG:2017-09-15 11:39:10.686[debug] <== Total: 1
说明: 在动态sql解析过程, #{}
与 ${}
的效果是不一样的
#{}
将传入的参数当成一个字符串,会给传入的参数加一个双引号${}
将传入的参数直接显示生成在sql中,不会添加引号#{}
能够很大程度上防止sql注入,${}
无法防止sql注入${}
在预编译之前已经被变量替换了,这会存在sql注入的风险
接下来展示一个sql注入的示例
接口定义
public List<TbTest> tableDynamic(@Param("tableName") String tableName);
Xml编写
<select id="tableDynamic" resultType="com.boot.stream.domain.mint.TbTest" statementType="STATEMENT">
select * from ${tableName} where 1=1
</select>
用例测试
@Test
public void sqlInject(){
// [{"age":88,"id":3,"name":"苏若年"},{"age":99,"id":4,"name":"墨少白"},{"age":66,"id":8,"name":"mock1"},{"age":77,"id":9,"name":"mock2"}]
System.out.println(JSON.toJSONString(tbTestMapper.tableDynamic("tb_test; delete from tb_test; --")));
// []
System.out.println(JSON.toJSONString(tbTestMapper.tableDynamic("tb_test")));
}
SQL执行
DEBUG:2017-09-15 12:06:49.867[debug] ==> Preparing: select * from tb_test; delete from tb_test; -- where 1=1
DEBUG:2017-09-15 12:06:49.868[debug] ==> Parameters:
DEBUG:2017-09-15 12:06:49.876[debug] <== Total: 4
DEBUG:2017-09-15 12:06:49.876[debug] <== Updates: 4
DEBUG:2017-09-15 12:06:49.878[debug] ==> Preparing: select * from tb_test where 1=1
DEBUG:2017-09-15 12:06:49.879[debug] ==> Parameters:
DEBUG:2017-09-15 12:06:49.882[debug] <== Total: 0
可以看到,因为SQL注入,导致表中所有数据被清除.
批量主键查询
接口定义
public List<TbTest> selectByIds(@Param("list") List<Long> ids);
Xml编写
<select id="selectByIds" resultType="com.boot.stream.domain.mint.TbTest">
SELECT
<include refid="sqlColumnList"/>
FROM
tb_test
where id IN
<foreach collection="list" item="li" open="(" separator="," close=")">
#{li}
</foreach>
</select>
用例测试
@Test
public void selectByIds(){
// [{"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}]
System.out.println(JSON.toJSONString(tbTestMapper.selectByIds(Lists.newArrayList(10L, 11L, 12L))));
}
SQL执行
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 ( ? , ? , ? )
DEBUG:2017-09-15 14:15:32.089[debug] ==> Parameters: 10(Long), 11(Long), 12(Long)
DEBUG:2017-09-15 14:15:32.123[debug] <== Total: 3
动态条件查询
接口定义
public List<TbTest> selectByCondition(@Param("object") TbTest tbTest);
Xml编写
<!-- 根据条件查询 -->
<select id="selectByCondition" resultType="com.boot.stream.domain.mint.TbTest">
SELECT
<include refid="sqlColumnList"/>
FROM
tb_test
<include refid="sqlQueryCondition"/>
<include refid="sqlSortByList"/>
</select>
<!-- 表字段集 -->
<sql id="sqlColumnList">
<trim suffixOverrides=",">
id AS id, name AS name, age AS age, create_time AS createTime, update_time AS updateTime,
</trim>
</sql>
<!-- 查询条件 -->
<sql id="sqlQueryCondition">
<trim suffixOverrides="," prefixOverrides="AND|OR">
<where>
<choose>
<when test="object.id > 0">
id = #{object.id}
</when>
<otherwise>
<if test="object.name != null">
AND name = #{object.name}
</if>
<if test="object.age != null">
AND age = #{object.age}
</if>
<if test="object.createTime">
AND create_time = #{object.createTime}
</if>
<if test="object.updateTime">
AND update_time = #{object.updateTime}
</if>
</otherwise>
</choose>
</where>
</trim>
</sql>
<!-- 结果集排序集合 -->
<sql id="sqlSortByList">
ORDER BY
<trim suffixOverrides=",">
id DESC, update_time DESC, create_time DESC, age DESC,
</trim>
</sql>
用例测试
@Test
public void selectByCondition(){
// 条件含主键查询:[{"age":88,"createTime":1505455272000,"id":10,"name":"苏若年","updateTime":1505455274000}]
System.out.println("条件含主键查询:" + JSON.toJSONString(tbTestMapper.selectByCondition(TbTest.builder().id(10L).build())));
// 条件非主键查询:[{"age":99,"createTime":1505455272000,"id":12,"name":"林允儿","updateTime":1505455274000},{"age":99,"createTime":1505455272000,"id":11,"name":"墨少白","updateTime":1505455274000}]
System.out.println("条件非主键查询:" + JSON.toJSONString(tbTestMapper.selectByCondition(TbTest.builder().age(99L).build())));
}
SQL执行
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
DEBUG:2017-09-15 14:18:26.659[debug] ==> Parameters: 10(Long)
DEBUG:2017-09-15 14:18:26.700[debug] <== Total: 1
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
DEBUG:2017-09-15 14:18:26.723[debug] ==> Parameters: 99(Long)
DEBUG:2017-09-15 14:18:26.727[debug] <== Total: 2
点击下方二维码, 关注【异次猿】
以上是关于MyBatis常用操作示例的主要内容,如果未能解决你的问题,请参考以下文章
Mybatis -- 动态Sql概述动态Sql之<if>(包含<where>)动态Sql之<foreach>sql片段抽取