我的其他文章也讲解的比较有趣,如果喜欢博主的讲解方式,可以多多支持一下,感谢!
了解 MyBatis 结果映射 请看 : MyBatis 结果映射详解!
其他优质专栏: 【SpringBoot】【多线程】【Redis】【✨设计模式专栏(已完结)】…等
如果喜欢作者的讲解方式,可以点赞收藏加关注,你的支持就是我的动力
✨更多文章请看个人主页: 码熔burning
这篇文章让我来好好讲解一下 MyBatis 的动态 SQL。
动态 SQL 是指在 SQL 语句中,根据不同的条件或参数,生成不同的 SQL 语句。 在传统的 SQL 语句中,SQL 语句是固定的,无法根据不同的情况进行变化。 而动态 SQL 可以根据不同的条件,动态地拼接 SQL 语句,从而满足不同的查询需求。
MyBatis 提供了强大的动态 SQL 功能,允许你根据运行时条件构建 SQL 语句。这使得你可以编写更灵活、可维护的 SQL 映射。
MyBatis 提供了一系列标签来构建动态 SQL。 以下是常用的标签及其用法:
: 条件判断
、
、
: 多条件选择
: 智能 WHERE
子句
: 智能 SET
子句
: 循环遍历
、
: SQL 片段重用
标签用于进行条件判断。 只有当 test
属性中的表达式为 true
时,才会将标签内的 SQL 片段添加到最终的 SQL 语句中。
<select id="findUsersByCondition" parameterType="map" resultType="User">
SELECT * FROM users
WHERE 1=1
<if test="username != null and username != ''">
AND username LIKE #{username}
if>
<if test="email != null and email != ''">
AND email = #{email}
if>
select>
解释:
id="findUsersByCondition"
:定义了一个名为 findUsersByCondition
的查询。parameterType="map"
:指定参数类型为 map
,这意味着你可以传递一个 Map
对象作为参数。resultType="User"
:指定结果类型为 User
类。WHERE 1=1
:这是一个小技巧,用于避免在第一个条件前出现 AND
或 OR
关键字,导致 SQL 语法错误。 如果第一个
标签的条件成立,则会添加 AND
关键字,否则不会添加。
:如果 username
不为 null
且不为空字符串,则添加 AND username LIKE #{username}
到 SQL 语句中。
:如果 email
不为 null
且不为空字符串,则添加 AND email = #{email}
到 SQL 语句中。#{username}
和 #{email}
:是 MyBatis 的参数占位符,用于将参数值安全地替换到 SQL 语句中。Java 代码示例:
Map<String, Object> params = new HashMap<>();
params.put("username", "%john%");
params.put("email", "[email protected]");
List<User> users = sqlSession.selectList("findUsersByCondition", params);
生成的 SQL 语句示例:
如果 username
和 email
都不为空,则生成的 SQL 语句如下:
SELECT * FROM users
WHERE 1=1
AND username LIKE '%john%'
AND email = '[email protected]'
如果只有 username
不为空,则生成的 SQL 语句如下:
SELECT * FROM users
WHERE 1=1
AND username LIKE '%john%'
标签类似于 Java 中的 switch
语句,用于多条件选择。 它包含多个
标签和一个
标签。 MyBatis 会按照顺序评估每个
标签的 test
属性,如果有一个
标签的 test
属性为 true
,则执行该
标签内的 SQL 片段,并跳过其他的
和
标签。 如果所有的
标签的 test
属性都为 false
,则执行
标签内的 SQL 片段。
<select id="findUsersByCondition" parameterType="map" resultType="User">
SELECT * FROM users
WHERE
<choose>
<when test="username != null and username != ''">
username LIKE #{username}
when>
<when test="email != null and email != ''">
email = #{email}
when>
<otherwise>
1=1
otherwise>
choose>
select>
解释:
:定义一个多条件选择结构。
:如果 username
不为 null
且不为空字符串,则添加 username LIKE #{username}
到 SQL 语句中。
:如果 email
不为 null
且不为空字符串,则添加 email = #{email}
到 SQL 语句中。
:如果 username
和 email
都为空,则添加 1=1
到 SQL 语句中,表示查询所有用户。Java 代码示例:
Map<String, Object> params = new HashMap<>();
// params.put("username", "%john%"); // 只设置 username
// params.put("email", "[email protected]"); // 只设置 email
List<User> users = sqlSession.selectList("findUsersByCondition", params);
生成的 SQL 语句示例:
如果 username
不为空,则生成的 SQL 语句如下:
SELECT * FROM users
WHERE
username LIKE '%john%'
如果 email
不为空,则生成的 SQL 语句如下:
SELECT * FROM users
WHERE
email = '[email protected]'
如果 username
和 email
都为空,则生成的 SQL 语句如下:
SELECT * FROM users
WHERE
1=1
标签用于智能地添加 WHERE
子句。 它会自动判断是否需要添加 WHERE
关键字,并自动去除多余的 AND
或 OR
关键字。
<select id="findUsersByCondition" parameterType="map" resultType="User">
SELECT * FROM users
<where>
<if test="username != null and username != ''">
username LIKE #{username}
if>
<if test="email != null and email != ''">
AND email = #{email}
if>
where>
select>
解释:
:智能地添加 WHERE
子句。
标签的条件成立,则
标签会自动添加 WHERE
关键字,并去除第一个 AND
关键字。
标签的条件都不成立,则
标签不会添加任何内容。Java 代码示例:
Map<String, Object> params = new HashMap<>();
params.put("username", "%john%");
params.put("email", "[email protected]");
List<User> users = sqlSession.selectList("findUsersByCondition", params);
生成的 SQL 语句示例:
如果 username
和 email
都不为空,则生成的 SQL 语句如下:
SELECT * FROM users
WHERE username LIKE '%john%'
AND email = '[email protected]'
如果只有 username
不为空,则生成的 SQL 语句如下:
SELECT * FROM users
WHERE username LIKE '%john%'
如果 username
和 email
都为空,则生成的 SQL 语句如下:
SELECT * FROM users
标签用于智能地添加 SET
子句。 它会自动判断是否需要添加 SET
关键字,并自动去除最后一个逗号。 通常用于 UPDATE
语句中。
<update id="updateUser" parameterType="User">
UPDATE users
<set>
<if test="username != null and username != ''">
username = #{username},
if>
<if test="email != null and email != ''">
email = #{email},
if>
set>
WHERE id = #{id}
update>
解释:
:智能地添加 SET
子句。
标签的条件成立,则
标签会自动添加 SET
关键字,并去除最后一个逗号。
标签的条件都不成立,则
标签不会添加任何内容。Java 代码示例:
User user = new User();
user.setId(1);
user.setUsername("new_username");
// user.setEmail("[email protected]"); // 不更新 email
sqlSession.update("updateUser", user);
生成的 SQL 语句示例:
如果 username
不为空,则生成的 SQL 语句如下:
UPDATE users
SET username = 'new_username'
WHERE id = 1
如果 username
和 email
都不为空,则生成的 SQL 语句如下:
UPDATE users
SET username = 'new_username',
email = '[email protected]'
WHERE id = 1
标签用于循环遍历集合。 它可以用于构建 IN
子句、批量插入等场景。
<select id="findUsersByIds" parameterType="list" resultType="User">
SELECT * FROM users
WHERE id IN
<foreach item="id" collection="list" open="(" separator="," close=")">
#{id}
foreach>
select>
解释:
item="id"
:指定集合中的每个元素的名字为 id
。collection="list"
:指定要遍历的集合的名字为 list
。 如果参数是数组,则 collection
属性的值为 array
。open="("
:指定循环开始时的字符串为 (
。separator=","
:指定每个元素之间的分隔符为 ,
。close=")"
:指定循环结束时的字符串为 )
。#{id}
:表示集合中的每个元素的值。Java 代码示例:
List<Integer> ids = Arrays.asList(1, 2, 3);
List<User> users = sqlSession.selectList("findUsersByIds", ids);
生成的 SQL 语句示例:
SELECT * FROM users
WHERE id IN (1,2,3)
批量插入示例:
<insert id="insertUsers" parameterType="list">
INSERT INTO users (username, email) VALUES
<foreach item="user" collection="list" separator=",">
(#{user.username}, #{user.email})
foreach>
insert>
Java 代码示例:
List<User> users = new ArrayList<>();
users.add(new User("john", "[email protected]"));
users.add(new User("jane", "[email protected]"));
sqlSession.insert("insertUsers", users);
生成的 SQL 语句示例:
INSERT INTO users (username, email) VALUES
('john', '[email protected]'),
('jane', '[email protected]')
标签用于定义 SQL 片段,
标签用于引用 SQL 片段。 这可以提高代码的复用性。 ♻️
<sql id="userColumns">
id, username, email
sql>
<select id="findAllUsers" resultType="User">
SELECT <include refid="userColumns"/> FROM users
select>
<select id="findUserById" parameterType="int" resultType="User">
SELECT <include refid="userColumns"/> FROM users WHERE id = #{id}
select>
解释:
:定义一个名为 userColumns
的 SQL 片段,包含 id, username, email
。
:引用名为 userColumns
的 SQL 片段。生成的 SQL 语句示例:
findAllUsers
生成的 SQL 语句:
SELECT id, username, email FROM users
findUserById
生成的 SQL 语句:
SELECT id, username, email FROM users WHERE id = 1
MyBatis 的动态 SQL 功能非常强大,可以根据不同的条件生成不同的 SQL 语句,从而满足不同的查询需求。 掌握这些标签的用法,可以编写更灵活、可维护的 SQL 映射。
一些建议:
#{}
可以有效地防止 SQL 注入。希望这篇文章能够帮助你理解 MyBatis 的动态 SQL。