
Mybatis动态SQL官方文档:Mybatis动态SQL官方文档
一、 if 标签
在我们的数据库表中有些字段不是必须要填的,数据库可以在不填的时候自动帮我们赋值。
那如果在添加⽤⼾的时候有不确定的字段传⼊,程序应该如何实现呢,这时候就需要动态SQL来实现。
if 标签就跟 if 语句一样,满足条件执行标签里面的内容。
<insert id="insertOne1">
insert into user_info (username, password, age
<if test="gender != null">
,gender
</if>
) values (#{username},#{password},#{age}
<if test="gender != null">
,#{gender}
</if>
)
</insert>
测试方法:
@Test
void insertOne1() {
UserInfo userInfo = new UserInfo();
userInfo.setAge(13);
userInfo.setPassword("1313");
userInfo.setUsername("1313");
userInfo.setGender(null);
Integer result = userMapperXML.insertOne1(userInfo);
System.out.println("增加函数:"+ result+", 增加数据的id:"+userInfo.getId());
}
结果:
可以看到结果中匹配的SQL语句中并没有gender字段。
注意事项:
- if 标签中test属性就相当于判断条件,里面的内容必须是java类的属性名,不能是字段名。
- 在使用插入语句时,一定要注意values前后对应字段都要有if标签,否则在不满足if条件的时候,前后字段数量就不对应了。
- 使用注解直接在上面的SQL语句加上script标签放入注解。
二、 trim标签
在上面的 if 标签里面我们有可能写出下面的代码:
<insert id="insertOne1">
insert into user_info (
<if test="gender != null">
age
</if>
<if test="gender != null">
,gender
</if>
) values (
<if test="gender != null">
#{age}
</if>
<if test="gender != null">
,#{gender}
</if>
)
</insert>
这样的代码,我们无法在age不满足,gender满足的条件下去掉逗号,这会导致这种情况下SQL语句错误。
这种时候就需要 trim 标签了。
trim 标签中有如下属性:
- prefix:表⽰整个语句块,以prefix的值作为前缀
- suffix:表⽰整个语句块,以suffix的值作为后缀
- prefixOverrides:表⽰整个语句块要去除掉的前缀
- suffixOverrides:表⽰整个语句块要去除掉的后缀
<insert id="insertOne2">
insert into user_info
<trim prefix="(" suffix=")" suffixOverrides=",">
username, password,
<if test="age != null">
age,
</if>
<if test="gender != null">
lgender
</if>
</trim>
values
<trim prefix="(" suffix=")" suffixOverrides=",">
#{username},#{password},
<if test="age != null">
#{age},
</if>
<if test="gender != null">
#{gender}
</if>
</trim>
</insert>
测试方法:
@Test
void insertOne2() {
UserInfo userInfo = new UserInfo();
userInfo.setAge(13);
userInfo.setPassword("1313");
userInfo.setUsername("1313");
userInfo.setGender(null);
Integer result = userMapperXML.insertOne2(userInfo);
System.out.println("增加函数:"+ result);
}
结果:
三、 where标签
当我们使用条件查询的时候,有以下SQl语句的时候。
select * Ffrom user_info where gender = 1 and phone = 0
我们需要根据传入的参数来进行条件查询,我们的xml文件写的如下:
<select id="selectWhere" resultType="com.example.springmybatisdemo.model.UserInfo">
select * from user_info where
<if test="gender != null">
gender = #{gender}
</if>
<if test="phone != null">
and phone = #{phone}
</if>
</select>
但是我们可以预料到,当gender不符合 if 条件,phone符合条件和两个都不符合条件时的SQl语句是一定会错的。
这个时候就需要使用到where标签了。
- where 标签 只会在⼦元素有内容的情况下才插⼊where⼦句,⽽且会⾃动去除⼦句的开头的 and 或 or
<select id="selectWhere" resultType="com.example.springmybatisdemo.model.UserInfo">
select * from user_info
<where>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="phone != null">
and phone = #{phone}
</if>
</where>
</select>
测试方法:
@Test
void selectWhere() {
UserInfo userInfo = new UserInfo();
userInfo.setGender(1);
//userInfo.setPhone("0");
userMapperXML.selectWhere(userInfo);
}
结果:
四、 set标签
当我们使用update - set进行更新操作的时候。
我们有以下的SQL语句:
update user_info
set username = 'username', password = 'password' , gender = 'gender' where id = 11
转化成xml文件如下:
<update id="updateTwo">
update user_info set
<if test="username != null">
username = #{username}
</if>
<if test="password != null">
,password = #{password}
</if>
<if test="gender != null">
,gender = #{gender}
</if>
where id = #{id}
</update>
可以看出当我们的username 不符合条件的时候,会在set后面多出一个逗号,让我们SQL语法错误。
- set 标签动态的在SQL语句中插⼊set关键字,并会删掉额外的逗号. (⽤于update语句中)
<update id="updateTwo">
update user_info
<set>
<if test="username != null">
username = #{username}
</if>
<if test="password != null">
,password = #{password}
</if>
<if test="gender != null">
,gender = #{gender}
</if>
</set>
where id = #{id}
</update>
测试方法:
@Test
void updateTwo() {
UserInfo userInfo = new UserInfo();
userInfo.setId(13);
userInfo.setPassword("6666");
//userInfo.setUsername("6666");
userInfo.setGender(1);
Integer result = userMapperXML.updateTwo(userInfo);
}
结果:
五、foreach标签
当我们要使用批量增删改查的时候,例如下面的SQL语句:
select * from user_info where id in (1,2,3)
select * from user_info where id = 1 or id = 2 or id = 3
# <foreach collection="ids" item="id" separator="or">
# id = #{id}
# </foreach>
select * from user_info where (username ,password) in
( ('admin','admin'),('zhangsan','zhangsan'),('lisi','lisi'))
# <foreach collection="userInfos" item="userInfo" separator=",">
# (#{userInfo.username}, #{userInfo.password})
# </foreach>
我们转换成xml文件,就需要使用 foreach 标签。
foreach 标签有如下属性:
- collection:绑定⽅法参数中的集合,如 List,Set,Map或数组对象
- item:遍历时的每⼀个对象
- open:语句块开头的字符串
- close:语句块结束的字符串
- separator:每次遍历之间间隔的字符串
如第一个SQL语句的xml文件如下:
<select id="selectEach" resultType="com.example.springmybatisdemo.model.UserInfo">
select * from user_info where id in
<foreach collection="ids" open="(" close=")" item="id" separator=",">
#{id}
</foreach>
</select>
测试代码:
@Test
void selectEach() {
List<Integer> ids = new ArrayList<>();
ids.add(1);
ids.add(2);
ids.add(3);
userMapperXML.selectEach(ids);
}
结果:
六、include标签和sql标签
当我们的代码中有很多重复片段时,可以对重复的代码⽚段进⾏抽取,将其通过 sql 标签封装到⼀个SQL⽚段,然后再通过 include 标签进⾏引⽤。
- sql 标签 定义可重⽤的SQL⽚段
- include 标签通过属性refid,指定包含的SQL⽚段
<sql id="sqlSelect">
select * from
</sql>
<select id="selectAll" resultType="com.example.springmybatisdemo.model.UserInfo" resultMap="UserMap">
<include refid="sqlSelect"></include>
user_info
</select>
测试方法:
@Test
void selectAll() {
System.out.println(userMapperXML.selectAll());
}
结果
MyBatis generator插件
MyBatis generator官方文档:MyBatis generator官方文档
引入依赖:
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.6</version>
<executions>
<execution>
<id>Generate MyBatis Artifacts</id>
<phase>deploy</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<!--generator配置⽂件所在位置-->
<configurationFile>src/main/resources/mybatisGenerator/generatorConfig.xml</con
figurationFile>
<!-- 允许覆盖⽣成的⽂件, mapxml不会覆盖, 采⽤追加的⽅式-->
<overwrite>true</overwrite>
<verbose>true</verbose>
<!--将当前pom的依赖项添加到⽣成器的类路径中-->
<includeCompileDependencies>true</includeCompileDependencies>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
</dependencies>
</plugin>
引入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">
<!-- 配置生成器 -->
<generatorConfiguration>
<!-- 一个数据库一个context -->
<context id="MysqlTables" targetRuntime="MyBatis3Simple" defaultModelType="flat">
<!--去除注释-->
<commentGenerator>
<property name="suppressDate" value="true"/>
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!--数据库链接信息-->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://127.0.0.1:3306/java_blog_spring?serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true"
userId="root"
password="root">
</jdbcConnection>
<!-- 生成实体类 -->
<javaModelGenerator targetPackage="com.example.demo.model" targetProject="src/main/java" >
<property name="enableSubPackages" value="false"/>
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- 生成mapxml文件 -->
<sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources" >
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- 生成mapxml对应client,也就是接口dao -->
<javaClientGenerator targetPackage="com.example.demo.mapper" targetProject="src/main/java" type="XMLMAPPER" >
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!-- table可以有多个,每个数据库中的表都可以写一个table,tableName表示要匹配的数据库表,也可以在tableName属性中通过使用%通配符来匹配所有数据库表,只有匹配的表才会自动生成文件 -->
<table tableName="user">
<property name="useActualColumnNames" value="false" />
<!-- 数据库表主键 -->
<generatedKey column="id" sqlStatement="Mysql" identity="true" />
</table>
</context>
</generatorConfiguration>
保持pom文件与xml文件中的路径名称一致。
- 记得在xml文件中修改要使用的数据库,以及密码。
- 实体类的路径
- Mapper的路径
- 操作的表名
在双击插件即可生成:
要想生成动态sql语句,直接将xml配置 中的Simple去掉即可。