动态 SQL 实战

笔记/Java/Java 持久层/MyBatis/动态 SQL 实战

前置:user 表 CRUD

1. 扩展 UserMapper.java#

List<User> search(@Param("userName") String userName,
@Param("status") Integer status);
int batchInsert(@Param("list") List<User> list);

2. 在 UserMapper.xml 追加#

<select id="search" resultMap="UserMap">
SELECT id, user_name, email, status, created_at FROM user
<where>
<if test="userName != null and userName != ''">
AND user_name LIKE CONCAT('%', #{userName}, '%')
</if>
<if test="status != null">
AND status = #{status}
</if>
</where>
ORDER BY id
</select>
<insert id="batchInsert">
INSERT INTO user (user_name, email, status) VALUES
<foreach collection="list" item="u" separator=",">
(#{u.userName}, #{u.email}, #{u.status})
</foreach>
</insert>
  • <where> 自动去掉多余 AND
  • 模糊查询用 CONCAT + #{},不要用 '${userName}'(防注入)
  • <foreach> 批量插入多行 VALUES

3. DynamicSqlDemo.java#

package demo.mybatis;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.util.List;
public class DynamicSqlDemo {
public static void main(String[] args) throws Exception {
try (InputStream in = Resources.getResourceAsStream("mybatis-config.xml")) {
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
try (SqlSession session = factory.openSession(true)) {
UserMapper mapper = session.getMapper(UserMapper.class);
System.out.println("search name contains 'li':");
mapper.search("li", null).forEach(System.out::println);
System.out.println("search status=1:");
mapper.search(null, 1).forEach(System.out::println);
List<User> batch = List.of(
new User("diana", "diana@example.com", 1),
new User("eric", "eric@example.com", 1)
);
mapper.batchInsert(batch);
System.out.println("batchInsert done, count=" + mapper.selectByStatus(1).size());
for (User u : batch) {
if (u.getId() != null) {
mapper.deleteById(u.getId());
}
}
for (User u : mapper.search("di", null)) {
mapper.deleteById(u.getId());
}
}
}
}
}

注意:batchInsertuser.getId() 若未配置 useGeneratedKeys 可能为空;Demo 末尾用 search("di") 清理插入行。生产环境批量 insert 可逐条 insert 或配合 ExecutorType.BATCH

4. 运行#

Terminal window
mvn -q exec:java -Dexec.mainClass=demo.mybatis.DynamicSqlDemo

#{}${}(面试)#

写法说明
#{}预编译 ?,用于参数值
${}字符串替换,仅用于表名/列名/ORDER BY,需白名单

下一篇:事务与批量

文章目录

文章目录