一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第18天,点击查看活动详情。
写在前面👀
承接上文,Mybatis 快速入门(二)☁ 、Mybatis 快速入门(三)🚀
今天主要讲讲动态SQL的选择条件动态查询和主键返回
一、动态SQL
手动拼接SQL语句是一件非常痛苦的事,动态 SQL 可以减少编写代码的工作量,体现了 MyBatis 的灵活性、高度可配置性和可维护性
- 动态SQL标签概述表👇
| 元素 | 作用 | 备注 |
|---|---|---|
| if | 判断语句 | 单条件分支判断 |
| choose、when、otherwise | 相当于 Java 中的 switch case 语句 | 多条件分支判断 |
| trim、where | 辅助元素 | 用于处理一些SQL拼装问题 |
| foreach | 循环语句 | 在in语句等列举条件常用 |
| bind | 辅助元素 | 拼接参数,模糊查询 |
- if和where标签比较容易,所以我就简单讲一下。
1️⃣if标签
- MyBatis if 类似于 Java 中的 if 语句,是 MyBatis 中最常用的判断语句。
a.语法
- 当判断条件为 true 时,才会执行所包含的 SQL 语句
<if test="判断条件">
SQL语句
</if>
b.示例
<!-- 根据姓名模糊查询-->
<select id="searchAllByName" resultMap="OpResultMap">
select *
from tb_op
<if test="name != null and name != ''">
where name like CONCAT('%', #{name}, '%')
</if>
</select>
2️⃣where标签
- where 标签主要用来简化 SQL 语句中的条件判断,可以自动处理 AND/OR 条件,避免了多条件查询时
WHERE 1=1的尴尬
a.语法
- where 标签经常和if标签放在一起用,if 语句中判断条件为 true 时,where 关键字才会加入到组装的 SQL 里面,否则就不加入。where 会检索语句,它会将 where 后的第一个 SQL 条件语句的 AND 或者 OR 关键词去掉。
<where>
<if test="判断条件">
AND/OR ...
</if>
</where>
b.示例
<!-- 根据id和赏金查询记录-->
<select id="searchByIdAndReward" resultMap="OpResultMap">
select *
from tb_op
<where>
<if test="id != null and id != 0">
and id <![CDATA[>]]> #{id}
</if>
<if test="reward != null">
and reward <![CDATA[>]]> #{reward};
</if>
</where>
</select>
二、选择条件动态查询
0️⃣需求
在查询时只能选择
性别、果实能力、身份这三个条件中的一个,或者一个条件都不选,查询默认的数据
- 这种需求可以用
choose(when,otherwise)标签
1️⃣choose-when-otherwise 语法
-
类似于Java中的switch-case-default
-
choose 标签按顺序判断其内部 when 标签中的判断条件是否成立,如果有一个成立,则执行相应的 SQL 语句,choose 执行结束;如果都不成立,则执行 otherwise 中的 SQL 语句。
<choose>
<when test="判断条件1">
SQL语句1
</when >
<when test="判断条件2">
SQL语句2
</when >
<when test="判断条件3">
SQL语句3
</when >
<otherwise>
SQL语句4
</otherwise>
</choose>
2️⃣编写接口方法
/**
* 5.在性别、果实、身份三个条件中,选择条件查询
* @param op
* @return List<Op>
*/
List<Op> searchByChoose(Op op);
3️⃣编写映射文件
<!--在性别、果实、身份三个条件中,选择条件查询-->
<select id="searchByChoose" resultMap="OpResultMap">
select *
from tb_op
where 1=1
<choose>
<when test="gender != null and gender != ''">
and gender = #{gender};
</when>
<when test="devilFruit !=null and devilFruit != ''">
and devil_fruit like concat('%',#{devilFruit},'%') ;
</when>
<when test="identity != null and identity != ''">
and identity like concat('%',#{identity},'%') ;
</when>
<otherwise>
and id=1;
</otherwise>
</choose>
</select>
4️⃣编写测试方法
@Test
/**
* 5.在性别、果实、身份三个条件中,选择条件查询
*/
public void testSearchByChoose() {
//三个条件都未选择,默认查询id为1的记录
String gender = null;
String devilFruit = null;
String identity = null;
//5.1创建Op对象
Op op = new Op();
//5.2调用方法封装对象
op.setGender(gender);
op.setDevilFruit(devilFruit);
op.setIdentity(identity);
System.out.println(op);
//5.3执行方法
List<Op> opList = opMapper.searchByChoose(op);
for (Op opValue : opList
) {
System.out.println(opValue);
}
//5.4释放资源
sqlSession.close();
}
- 演示结果如下👇
三、Insert, Update, Delete 元素属性
| 属性 | 描述 |
|---|---|
id | 在命名空间中唯一的标识符,可以被用来引用这条语句。 |
parameterType | 将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。 |
flushCache | 将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:(对 insert、update 和 delete 语句)true。 |
timeout | 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。 |
statementType | 可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。 |
useGeneratedKeys | (仅适用于 insert 和 update)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false。 |
keyProperty | (仅适用于 insert 和 update)指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)。如果生成列不止一个,可以用逗号分隔多个属性名称。 |
keyColumn | (仅适用于 insert 和 update)设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。 |
databaseId | 如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。 |
四、添加数据-主键返回
0️⃣需求
添加数据,并且在数据添加成功后,要获取插入数据库数据的主键
- 要满足需求,可以在insert 标签上添加如下属性🏴☠️
- useGeneratedKeys:能够获取自动增长的主键值。默认是false,
true表示获取 - keyProperty :指定将获取到的主键值封装到哪儿个属性里
- useGeneratedKeys:能够获取自动增长的主键值。默认是false,
1️⃣编写接口方法
/**
* 6.添加数据并返回主键
* @param op
* @return void
*/
void addAllOps(Op op);
2️⃣编写映射文件
<!-- 添加数据并返回主键-->
<insert id="addAllOps" useGeneratedKeys="true" keyProperty="id">
insert into tb_op (name, gender, devil_fruit, reward, identity)
values (#{name}, #{gender}, #{devilFruit}, #{reward}, #{identity});
</insert>
3️⃣编写测试方法
@Test
/**
* 6.添加数据并返回主键
*/
public void testAddAllOps() {
//添加数据
String name = "马尔科";
String gender = "男";
String devilFruit = "鸟鸟果实-幻兽种-不死鸟形态";
Long reward = 1374000000L;
String identity = "海贼";
//6.1创建Op对象
Op op = new Op();
//6.2调用方法封装对象
op.setName(name);
op.setGender(gender);
op.setDevilFruit(devilFruit);
op.setReward(reward);
op.setIdentity(identity);
//6.3执行方法
opMapper.addAllOps(op);
//6.4调用getter方法获取主键
Integer id = op.getId();
//6.6根据返回的主键值查询相关信息
System.out.println(opMapper.searchById(id));
//6.7释放资源
sqlSession.close();
}
- 演示结果如下👇
写在后面🍻
感谢观看啦✨
有什么不足,欢迎指出哦💖
掘金的运营同学审核辛苦了💗