mybatis框架中的动态sql
-
为什么要使用动态sql
- 我们使用mybatis框架进行数据库表进行CRUD操作时,当我们写的 SQL 语句都比较简单,还比较容易实现,但如果有比较复杂的业务,就需要便写复杂的 SQL 语句,往往需要拼接,而拼接 SQL ,稍微不注意,由于引号,空格等缺失可能都会导致错误。
-
我们如何解决这个问题呢
-
这就是我们要说的使用mybatis 动态SQL,使用if, choose, when, otherwise, trim, where, set, foreach等标签,可以轻松组成非常灵活的SQL语句,这样就可以在提高 SQL 语句的准确性的同时,也大大提高了开发人员的效率。
-
当不使用动态sql语句时;
<!--parameterType传入参数数据类型,resultType返回值数据类型,要注意,查询的字段要和po中实体类的属性值对应,否则就睡映射不上--> <select id="selectLike" parameterType="string" resultType="com.wdhcr.mybatisSelectLike.po.User"> <!-- 我们不使用动态sql语句时,当传参name为空时,查询也就为空--> select * from user01 where name where name= #{name} </select>
- 当使用动态sql中的if标签时
<!-- 动态sql中if语句的使用--> <select id="selectUserIf" parameterType="java.lang.String" resultType="com.wdhcr.mybatisDynamicSql.po.User"> select * from user01 where <!-- 如果使用动态sql时 string类型的数据需要使用 _parameter 作为形参名, 否则就会出现string无get方法,当if中的条件不满足时,if中的语句就不会给主体的sql语句上加--> <if test="_parameter != null"> name = #{_parameter} </if> </select>
- 当使用动态sql中的 if where标签连用时
<!-- 动态sql中if where连用--> <select id="selectUserIfWhere" parameterType="java.lang.String" resultType="com.wdhcr.mybatisDynamicSql.po.User"> select * from user01 <!-- 当有where标签时,第一个if判断中可以不加and 或者or,加上,where也会为我们自动去掉,但后面的if中要加--> <where> <!-- 如果使用动态sql时 string类型的数据需要使用 _parameter 作为形参,否则就会出现string无get方法--> <if test="_parameter != null"> name = #{_parameter} </if> </where> </select>
- 当使用动态sql中的set ,if, where标签连用,set标签主要是在更新语句中使用充当set使用
<!-- 动态sql中的set ,if where连用--> <update id="updateUser" parameterType="com.wdhcr.mybatisDynamicSql.po.User"> update user01 <set> <!-- 注意这是sql拼接,要注意拼接成功后的sql语句,要和正常的sql语句语法相同, 当set中有多个字段时每个字段后面要加上","要符合正常的sql语句--> <if test="password != null and password != ''"> user01.password = #{password} </if> </set> <where> <if test="name != null and name !=''"> name = #{name} </if> </where> </update>
- 当使用动态sql中的trim标签
<!-- 动态sql中的trim的使用--> <select id="selectTrimUser" parameterType="string" resultType="com.wdhcr.mybatisDynamicSql.po.User"> select * from user01 <!-- prefixOverrides是自动设置前缀的 suffixOverrides是设置标签中的sql语句后缀自动加上你设置的符号例如','--> <trim prefix="where" prefixOverrides="and/or" > <if test="_parameter != null"> name = #{_parameter} </if> </trim> </select>
- 当使用动态sql中的choose ,when,otherwise标签连用
<select id="selectChoose" parameterType="string" resultType="com.wdhcr.mybatisDynamicSql.po.User"> select * from user01 <where> <!-- 相当与java里面的switch语句,when相当于case,当条件满足时,执行,--> <!-- 并且其他的就不会执行了,当所有when都没有时,执行otherwise中的语句--> <choose> <when test="_parameter == '王大锤'"> user01.name = #{_parameter} </when> <otherwise> user01.name = "王八羔子" </otherwise> </choose> </where> </select>
- 当使用动态sql中的sql片段标签,java开发就是讲究高内聚,低耦合嘛,所以把相同重复度高的sql片段抽取出来。
<!-- 动态sql中的sql片段使用--> <!-- 创建sql片段--> <sql id="choseName"> <if test="_parameter != null"> name = #{_parameter} </if> </sql> <select id="selectSqlUser" parameterType="string" resultType="com.wdhcr.mybatisDynamicSql.po.User"> select * from user01 <!-- 调用sql片段--> <where> <include refid="choseName"></include> </where> </select>
- 我们向数据库中比如需要查询name= zz or name=qq or name=ww的使用,我们可以传过来一个list,我们就可以使用动态sql中的foreach标签
<!--动态sql中的foreach循环--> <!--使用动态sql的sql片段--> <sql id="foreach"> <if test="list != null"> <!-- collection:指定输入对象中的集合属性 item:每次遍历生成的对象 open:开始遍历时的拼接字符串 close:结束时拼接的字符串 separator:遍历对象之间需要拼接的字符串 select * from user01 where 1=1 and (name=zz or name=qq or name=ww) --> <foreach collection="list" item="name_item" open="and (" close=")" separator="or"> name = #{name_item} </foreach> </if> </sql> <!--使用动态sql中的foreach查询传入参数为list时--> <select id="forSqlUser" parameterType="list" resultType="com.wdhcr.mybatisDynamicSql.po.User"> select * from user01 <where> <!--使用where标签它可以自动添加或删除where后面的and或者or--> <!--调用sql片段--> <include refid="foreach"></include> </where> </select>
- 用 foreach 来改写 select * from user01 where name in (‘zz’,‘qq’,‘ww’)
<select id="forUserByName" parameterType="list" resultType="com.wdhcr.mybatisDynamicSql.po.User"> select * from user01 <where> <!-- collection:指定输入对象中的集合属性 item:每次遍历生成的对象 open:开始遍历时的拼接字符串 close:结束时拼接的字符串 separator:遍历对象之间需要拼接的字符串 select * from user01 where 1=1 and name in ('aa','qq','ww') --> <if test="list != null"> <foreach collection="list" item="id" open="and name in (" close=") " separator=","> #{id} </foreach> </if> </where> </select>
- 当我们传入的数据类型为hashmap时如下:
<!--使用动态sql的foreach传入参数为hashmap时--> <select id="forUserMap" parameterType="hashmap" resultType="com.wdhcr.mybatisDynamicSql.po.User"> select * from user01 where name like concat('%',#{name},'%') and password in <if test="list != null"> <foreach collection="list" item="pass_item" open="(" separator="," close=")"> #{pass_item} </foreach> </if> </select>
-
-
以上就是动态sql比较常用的一些操作了
-
下面是一个完成的案例展示:
- maven依赖
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.8</version> </dependency> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
- 数据库字段结构
- 核心全局配置文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <environments default="dev"> <environment id="dev"> <!-- 设置事务类型--> <transactionManager type="JDBC"></transactionManager> <!-- 设置数据源类型--> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/一个库"/> <property name="username" value="用户名"/> <property name="password" value="密码"/> </dataSource> </environment> </environments> <!-- 注入你的映射文件--> <mappers> <mapper resource="UserSelectLike.xml"></mapper> <mapper resource="UserMapperSql.xml"></mapper> </mappers> </configuration>
- 映射文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.wdhcr.mybatisDynamicSql.mapper.UserMapperSql"> <!-- 动态sql中if语句的使用--> <select id="selectUserIf" parameterType="java.lang.String" resultType="com.wdhcr.mybatisDynamicSql.po.User"> select * from user01 where <!-- 如果使用动态sql时 string类型的数据需要使用 _parameter 作为形参名, 否则就会出现string无get方法,当if中的条件不满足时,if中的语句就不会给主体的sql语句上加--> <if test="_parameter != null"> name = #{_parameter} </if> </select> <!-- 动态sql中if where连用--> <select id="selectUserIfWhere" parameterType="java.lang.String" resultType="com.wdhcr.mybatisDynamicSql.po.User"> select * from user01 <!-- 当有where标签时,第一个if判断中可以不加and 或者or,加上,where也会为我们自动去掉,但后面的if中要加--> <where> <!-- 如果使用动态sql时 string类型的数据需要使用 _parameter 作为形参,否则就会出现string无get方法--> <if test="_parameter != null"> name = #{_parameter} </if> </where> </select> <!-- 动态sql中的set ,if where连用--> <update id="updateUser" parameterType="com.wdhcr.mybatisDynamicSql.po.User"> update user01 <set> <!-- 注意这是sql拼接,要注意拼接成功后的sql语句,要和正常的sql语句语法相同, 当set中有多个字段时每个字段后面要加上","要符合正常的sql语句--> <if test="password != null and password != ''"> user01.password = #{password} </if> </set> <where> <if test="name != null and name !=''"> name = #{name} </if> </where> </update> <!-- 动态sql中的trim的使用--> <select id="selectTrimUser" parameterType="string" resultType="com.wdhcr.mybatisDynamicSql.po.User"> select * from user01 <!-- prefixOverrides是自动设置前缀的 suffixOverrides是设置标签中的sql语句后缀自动加上你设置的符号例如','--> <trim prefix="where" prefixOverrides="and/or" > <if test="_parameter != null"> name = #{_parameter} </if> </trim> </select> <!-- 动态sql中使用choose ,when,otherwise--> <select id="selectChoose" parameterType="string" resultType="com.wdhcr.mybatisDynamicSql.po.User"> select * from user01 <where> <!-- 相当与java里面的switch语句,when相当于case,当条件满足时,执行,--> <!-- 并且其他的就不会执行了,当所有when都没有时,执行otherwise中的语句--> <choose> <when test="_parameter == '王大锤'"> user01.name = #{_parameter} </when> <otherwise> user01.name = "王八羔子" </otherwise> </choose> </where> </select> <!-- 动态sql中的sql片段使用--> <!-- 创建sql片段--> <sql id="choseName"> <if test="_parameter != null"> name = #{_parameter} </if> </sql> <select id="selectSqlUser" parameterType="string" resultType="com.wdhcr.mybatisDynamicSql.po.User"> select * from user01 <!-- 调用sql片段--> <where> <include refid="choseName"></include> </where> </select> <!--动态sql中的foreach循环--> <!--使用动态sql的sql片段--> <sql id="foreach"> <if test="list != null"> <!-- collection:指定输入对象中的集合属性 item:每次遍历生成的对象 open:开始遍历时的拼接字符串 close:结束时拼接的字符串 separator:遍历对象之间需要拼接的字符串 select * from user01 where 1=1 and (name=zz or name=qq or name=ww) --> <foreach collection="list" item="name_item" open="and (" close=")" separator="or"> name = #{name_item} </foreach> </if> </sql> <!--使用动态sql中的foreach查询传入参数为list时--> <select id="forSqlUser" parameterType="list" resultType="com.wdhcr.mybatisDynamicSql.po.User"> select * from user01 <where> <!--使用where标签它可以自动添加或删除where后面的and或者or--> <!--调用sql片段--> <include refid="foreach"></include> </where> </select> <!--使用动态sql的foreach传入参数为hashmap时--> <select id="forUserMap" parameterType="hashmap" resultType="com.wdhcr.mybatisDynamicSql.po.User"> select * from user01 where name like concat('%',#{name},'%') and password in <if test="list != null"> <foreach collection="list" item="pass_item" open="(" separator="," close=")"> #{pass_item} </foreach> </if> </select> </mapper>
- po层的实体类
/* * po层的实体类。里面的属性值对应数据库表中的字段 * 并生成它的get set方法 和tostring方法 * */ public class User { private String name; private String password; public User(String name, String password) { this.name =name; this.password = password; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", password='" + password + '\'' + '}'; } }
- 测试类代码
import com.wdhcr.mybatisDynamicSql.po.User; 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.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class Test { public static void main(String[] args) throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("ConfigMapper.xml"); SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = build.openSession(); //这是动态sql中用if // User user= sqlSession.selectOne("com.wdhcr.mybatisDynamicSql.mapper.UserMapperSql.selectUserIf", "王 大锤"); // System.out.println(user); //这是动态sql中用where 和if // User user= sqlSession.selectOne("com.wdhcr.mybatisDynamicSql.mapper.UserMapperSql.selectUserIfWhere", "王大锤"); // System.out.println(user); //动态sql中使用set where if set 主要使用在更新语句中 // sqlSession.update("com.wdhcr.mybatisDynamicSql.mapper.UserMapperSql.updateUser",new User("王八羔子","111111")); // //注意进行增删改操作时,一定要提交事务 // sqlSession.commit(); //动态sql中使用trim标签它可以模拟你常用的一些标签 // User user = sqlSession.selectOne("com.wdhcr.mybatisDynamicSql.mapper.UserMapperSql.selectTrimUser", "王大锤"); // System.out.println(user); //动态sql中的choose,when otherwise标签连用 // User user=sqlSession.selectOne("com.wdhcr.mybatisDynamicSql.mapper.UserMapperSql.selectChoose","王大大锤"); // System.out.println(user); //动态sql中将常用的一些sql片段封装起来,用的使用直接调用 // User user= sqlSession.selectOne("com.wdhcr.mybatisDynamicSql.mapper.UserMapperSql.selectSqlUser","王大锤"); // System.out.println(user); //动态sql中的foreach循环传入参数为list // List list = new ArrayList<>(); // list.add("王大锤"); // list.add("王八羔子"); // //userVo.setList(list); // List<User> userList=sqlSession.selectList("com.wdhcr.mybatisDynamicSql.mapper.UserMapperSql.forSqlUser",list); // for (User user : userList) { // System.out.println(user); // } //动态sql中的foreach循环,传入参数为hashmap List list = new ArrayList<>(); list.add("5678"); list.add("111111"); HashMap hashMap = new HashMap(); hashMap.put("list",list); hashMap.put("name","王大锤"); List<User> userList=sqlSession.selectList("com.wdhcr.mybatisDynamicSql.mapper.UserMapperSql.forUserMap",hashMap); for (User user : userList) { System.out.println(user); } } }
-
以上就是mybatis框架中的动态sql语句的讲解,和具体的代码案例使用。