该篇主要是Mybatis在日常开发中的使用积累, 对于Intellij IDEA 推荐一款Mybatis插件
Free Mybatis
Mybatis生成插件
mybatis-generator是一个可以生成mybatis通用代码的maven插件
插件引入
1 | <build> |
生成命令
1 | mvn mybatis-generator:generate |
配置说明
工程目录下:src/main/resources/generatorConfig.xml
1 |
|
Mybatis常用业务SQL
示例库表
1 | CREATE TABLE `tb_test` ( |
示例模型
1 |
|
示例操作
插入并返回主键
接口定义
1 | public int insertFullId(TbTest tbTest); |
Xml编写
1 | <insert id="insertFullId" useGeneratedKeys="true" keyProperty="id" parameterType="com.boot.stream.domain.mint.TbTest"> |
用例测试
1 |
|
SQL执行
1 | DEBUG:2017-09-15 10:49:48.041[debug] ==> Preparing: insert into tb_test (id, name, age, create_time, update_time) values (?, ?, ?,?, ?) |
执行结果
插入或者更新(记录存在则更新)
接口定义
1 | public void batchUpset(@Param("list") List<TbTest> list); |
Xml编写
1 | <insert id="batchUpset" parameterType="java.util.Collection"> |
用例测试
1 |
|
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) |
执行结果
批量更新(根据主键更新)
接口定义
1 | public void batchUpdate(@Param("list") List<TbTest> list); |
Xml编写
1 | <update id="batchUpdate" parameterType="java.util.Collection"> |
用例测试
1 |
|
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 = ? |
执行结果
批量插入
接口定义
1 | public void batchInsert(@Param("list") List<TbTest> list); |
Xml编写
1 | <insert id="batchInsert" useGeneratedKeys="true" keyProperty="id" parameterType="java.util.Collection"> |
用例测试
1 |
|
SQL执行
1 | DEBUG:2017-09-15 11:19:41.823[debug] ==> Preparing: insert into tb_test (name, age, create_time, update_time) values ( ?, ?, ?, ? ) , ( ?, ?, ?, ? ) |
执行结果
动态表/字段传递
接口定义
1 | public TbTest columnDynamic(@Param("column") String column, @Param("val") String s); |
Xml编写
1 | <select id="columnDynamic" resultType="com.boot.stream.domain.mint.TbTest"> |
用例测试
1 |
|
SQL执行
1 | DEBUG:2017-09-15 11:39:10.585[debug] ==> Preparing: select name from tb_test where name = ? |
MyBatis中使用#和$书写占位符有什么区别
说明: 在动态sql解析过程,#{}
与 ${}
的效果是不一样的, #将传入的数据都当成一个字符串,会对传入的数据自动加上引号;$将传入的数据直接显示生成在SQL中.
#{}
将传入的参数当成一个字符串,会给传入的参数加一个双引号${}
将传入的参数直接显示生成在sql中,不会添加引号#{}
能够很大程度上防止sql注入,${}
无法防止sql注入${}
在预编译之前已经被变量替换了,这会存在sql注入的风险- 写order by子句的时候应该用
${}
而不是#{}
接下来展示一个sql注入的示例
接口定义
1 | public List<TbTest> tableDynamic(@Param("tableName") String tableName); |
Xml编写
1 | <select id="tableDynamic" resultType="com.boot.stream.domain.mint.TbTest" statementType="STATEMENT"> |
用例测试
1 |
|
SQL执行
1 | DEBUG:2017-09-15 12:06:49.867[debug] ==> Preparing: select * from tb_test; delete from tb_test; -- where 1=1 |
可以看到,因为SQL注入,导致表中所有数据被清除.
解释一下MyBatis中命名空间(namespace)的作用
在大型项目中, 可能存在大量的SQL语句,这时候为每个SQL语句起一个唯一的标识(ID)就变得并不容易了。为了解决这个问题,在MyBatis中,可以为每个映射文件起一个唯一的命名空间,这样定义在这个映射文件中的每个SQL语句就成了定义在这个命名空间中的一个ID。只要我们能够保证每个命名空间中这个ID是唯一的,即使在不同映射文件中的语句ID相同,也不会再产生冲突了。
批量主键查询
接口定义
1 | public List<TbTest> selectByIds(@Param("list") List<Long> ids); |
Xml编写
1 | <select id="selectByIds" resultType="com.boot.stream.domain.mint.TbTest"> |
用例测试
1 |
|
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 ( ? , ? , ? ) |
动态条件查询
接口定义
1 | public List<TbTest> selectByCondition(@Param("object") TbTest tbTest); |
Xml编写
1 | <!-- 根据条件查询 --> |
用例测试
1 |
|
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 |