Mybatis 动态sql
目录
一、核心特点:
二、XML配
置方式实现动态sql
四、mybatis 动态sql xml配置与注解的优缺点
五、使用建议:
mybatis 动态sql是一种能够根据不同参数条件动态生成、拼接 SQL 语句的技术,它允许在 SQL 语句中嵌入条件判断、循环等逻辑,使得能根据运行时的参数情况自动调整最终执行的 SQL 结构。MyBatis 提供了两种实现动态 SQL 的方式:XML 配置和注解。这两种方式各有特点,适用于不同的场景。
一、核心特点:
1、条件性拼接:根据参数是否为空、是否满足特定条件,决定是否拼接对应的 SQL 片段(如 WHERE
子句中的条件)。
2、灵活性:无需手动拼接 SQL 字符串,避免因参数变化导致的语法错误(如多余的 AND
/OR
关键字)。
3、安全性:结合 MyBatis 的参数绑定机制,防止 SQL 注入风险。
4、复用性:支持通过 <sql>
标签定义可复用的动态 SQL 片段,减少冗余。
二、XML配
置方式实现动态sql
XML 方式是 MyBatis 最传统也最常用的动态 SQL 实现方式,通过<if><choose><when><othewise><trim><where><set><foreach> 等标签来实现动态 SQL 逻辑。
1、<where>标签:
(1)<where>作用:当where标签有内容时,会添加一个where 当where标签没有内容时不添加where , 当where标签会去掉紧跟在where关键词后面的第一个and或者or之类的连接符
<if>元素:< if test =”条件”> 语句 </if> 满足条件 执行语句
(2)使用:
<!-- sql 片段 可以截取sql片段 --><sql id="stusql">sid,sname,birthday,ssex,classid</sql><select id="getStudent" resultType="student">select<include refid="stusql"></include> from Student<where><if test="ssex !=null ">and ssex = #{ssex}</if><if test="classid != 0 ">and classid = #{classid}</if></where></select>
2、<choose>标签
(1)作用:只能有一个条件被使用 使用满足的第一个条件 条件都不满足使用 otherwise 有优先级
<when>元素:< when test =”条件”> 语句 </when> 满足条件 执行语句 一个choose里面最多执行一个when
(2)使用:
<select id="getStudentChoose" resultType="student">select <include refid="stusql"></include> from Student<where><choose><when test="ssex!=null">ssex=#{ssex}</when><when test="classid!=0">classid=#{classid}</when><otherwise>sid=10</otherwise></choose></where></select>
3、<set>标签
(1)作用:set 会自动添加一个set关键词 并去除最后一个逗号,
(2)使用:
<update id="updateStudent" parameterType="student">update student<set><if test="sname!=null">sname=#{sname},</if><if test="birthday!=null">birthday=#{birthday},</if><if test="ssex!=null">ssex=#{ssex},</if><if test="classid!=0">classid=#{classid},</if></set>where sid=#{sid}</update>
4、<trim>标签(万能标签)效率不高
(1)作用:可以实现自由拼接
<trim prefix="" prefixOverrides="" suffix="" suffixOverrides=""></trim>
//<!-- prefix="" 开始之前 添加一个什么 prefixOverrides="" 开始之前去掉一个什么 suffix="" 结束之前添加一个什么 suffixOverrides="" 结束之前去掉一个什么 -->
(2)使用
<select id="getStudentTrim" parameterType="student" resultType="student">select <include refid="stusql"></include> from Student<trim prefix="where" prefixOverrides="and" suffix="" suffixOverrides=""><if test="ssex!=null">and ssex=#{ssex}</if><if test="classid!=0">and classid=#{classid}</if></trim></select>
5、<foreach>标签
(1)作用:可以将数组集合等遍历拼接在sql语句上
<foreach collection="" item="" index="" open="" close="" separator=""> </foreach>
item 循环中的当前元素;
collection 方法传递的参数,一个数组或者集合;
close 以什么符号结束将这些集合元素包装 起来;
index 当前循环元素的位置下标;
open 以什么符号开始将这些集合元素包装 起来;
separator 各个元素的间隔符号
(2)使用
<select id="getStudentList" resultType="student">select<include refid="stusql"></include> from Student<where>sid in<foreach collection="list" item="x" open="(" close=")" separator=",">#{x}</foreach></where></select>
6、<bind>标签
(1)作用:可以定义变量 在sql语句中引用
<bind name="" value=""></bind>
name:变量名
value: 值
(2)使用:
<select id="getStudentBySnameLike" resultType="student" parameterType="String"><bind name="li" value="'%'+_parameterType+'%'"/>select * from student where sname like #{li};</select>
三、注解方式(动态sql)
1、使用sql脚本编写动态sql 使用<script>
@Select({"<script>" + "select * from student " +"<where>" +"<if test=\"ssex !=null \"> and ssex= #{ssex}</if>" +"<if test=\"classid !=0 \"> and classid =#{classid}</if>" +"</where>" + "</script>"})public List<Student> getstudent(Student s);
2、手动构建sql语句(不使用构造器)需要使用@xxxxtProvider(type= ,method=" ")注解
type: 类.class
method:类中的方法引用:
@SelectProvider(type = StuSql.class, method = "getStudentSqlSelect")public List<Student> getStudentFunc(Student s);@SelectProvider(type = StuSql.class, method = "getStudentSqlSelectGaoZao")public List<Student> getStudentGouZao(Student s);@InsertProvider(type = StuSql.class,method = "addStudentSqlInsertGuoZao")public int insertStudentGuoZao(Student s);@DeleteProvider(type = StuSql.class,method = "deleteStudentSqlInsertGuoZao")public int deleteStudentGuoZao(int sid);@UpdateProvider(type = StuSql.class,method = "updateStudentSqlInsertGuoZao")public int updateStudentGuoZao(Student s);class StuSql {//第一种手动构建public String getStudentSqlSelect(Student s) {String sql = "select * from Student where 1=1 ";if (s.getSsex() != null) {sql += "and ssex =#{ssex}";}if (s.getClassid() != 0) {sql += "and classid =#{classid}";}return sql;}}
3、使用构造器:需要使用@xxxxtProvider(type= ,method=" ")注解
type: 类.class
method:类中的方法引用:
(1) SELECT 查询:
@SelectProvider(type = StuSql.class, method = "getStudentSqlSelectGaoZao")public List<Student> getStudentGouZao(Student s);class StuSql {//使用构造器public String getStudentSqlSelectGaoZao(Student s) {return new SQL() {{SELECT("sid");SELECT("sname,birthday");SELECT("ssex", "classid");FROM("student");if (s.getSsex() != null) {WHERE("ssex=#{ssex}");}
// OR() 默认and 除非手动加OR()if (s.getClassid() != 0) {WHERE("classid=#{classid}");}}}.toString();}}
(2)INSERT: 增加
@InsertProvider(type = StuSql.class,method = "addStudentSqlInsertGuoZao")public int insertStudentGuoZao(Student s);class StuSql {public String addStudentSqlInsertGuoZao(Student s){return new SQL(){{INSERT_INTO("student");if(s.getSid()!=0){VALUES("sid","#{sid}");}if(s.getSname()!=null){VALUES("sname","#{sname}");}if(s.getBirthday()!=null){VALUES("birthday","#{birthday}");}if(s.getSsex()!=null){VALUES("ssex","#{ssex}");}if(s.getClassid()!=0){VALUES("classid","#{classid}");}}}.toString();}}
(3)DELETE : 删除
@DeleteProvider(type = StuSql.class,method = "deleteStudentSqlInsertGuoZao")public int deleteStudentGuoZao(int sid);class StuSql {public String deleteStudentSqlInsertGuoZao(int sid){return new SQL(){{DELETE_FROM("student");WHERE("sid=#{sid}");}}.toString();}}
(4)UPDATE:修改
@UpdateProvider(type = StuSql.class,method = "updateStudentSqlInsertGuoZao")public int updateStudentGuoZao(Student s);class StuSql {public String updateStudentSqlInsertGuoZao(Student s){return new SQL(){{UPDATE("student");if(s.getSname()!=null){SET("sname = #{sname}");}if(s.getBirthday()!=null){SET("birthday = #{birthday}");}if(s.getSsex()!=null){SET("ssex = #{ssex}");}if(s.getClassid()!=0){SET("classid = #{classid}");}WHERE("sid=#{sid}");}}.toString();}}
四、mybatis 动态sql xml配置与注解的优缺点
方式 | 优点 | 缺点 |
---|---|---|
XML 配置 | 1. SQL 与代码分离,结构清晰,可读性强; 2. 支持复杂动态逻辑和片段复用; 3. 便于 SQL 优化和团队协作; 4. 无需重新编译即可生效。 | 1. 需要维护额外的 XML 文件,项目结构稍显复杂; 2. 简单逻辑可能显得繁琐。 |
注解方式 | 1. 无需 XML 文件,代码集中,开发便捷; 2. 适合简单场景,学习成本低; 3. 与 Java 代码紧密结合,便于快速定位。 | 1. 复杂 SQL 逻辑导致代码臃肿,可读性差; 2. 循环、嵌套等操作需手动实现,易出错; 3. 修改 SQL 需重新编译,不适合频繁变更场景。 |
五、使用建议:
1、选择 XML 配置:当项目中存在复杂动态 SQL(如多条件组合查询、批量操作)、需要频繁优化 SQL 或团队协作时,XML 方式的可维护性和清晰性更具优势。
2、适当使用注解方式:对于简单的动态逻辑(如单表的基础 CRUD)或轻量级项目,注解方式可以简化配置,提高开发效率。
3、混合使用策略:在实际项目中,可根据场景灵活选择 —— 核心复杂逻辑用 XML,简单辅助逻辑用注解,但需保持团队风格统一。