针对模糊查询的三种方式
业务层传递数据,在映射文件取值时where语句理论上应写为where user_name like #{user_name}%,但实际上控制台会报错。
### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘%‘ at line 1
提示的是数据库Sql语句的错误,如果使用了log4j日志,控制台显示:
DEBUG [main] - ==> Preparing: select * from web_user where user_name like ?% DEBUG [main] - ==> Parameters: 悟(String)
后面会解释为什么会出错。所以直接取值是不行的,可以使用下面的几种方式。
一 在业务层进行处理
在业务层接收到数据时,首先对数据进行一次简单的处理操作。
//接口中的方法为List<User> where01(String user_name);try { sqlSession = MyBatisUtil.getSqlSession(); String user_name = "悟"; List<User> list = sqlSession.getMapper(UserDao.class).where01(user_name + "%"); logger.debug(list); } finally { MyBatisUtil.closeSqlSession(sqlSession); }
映射文件中的sql语句为:
<select id="where01" resultType="self.exercise.bean.User" parameterType="string"> select * from web_user where user_name like #{user_name} </select>
此时日志在控制台输出
DEBUG [main] - ==> Preparing: select * from web_user where user_name like ? DEBUG [main] - ==> Parameters: 悟%(String)
二 在映射文件取值时进行处理
在业务层不进行数据处理,在映射文件中不用#{}取值,改为${}方式取值。
<select id="where01" resultType="self.exercise.bean.User" parameterType="string"> select * from web_user where user_name like ‘${_parameter}%‘ </select>
控制台的信息:
DEBUG [main] - ==> Preparing: select * from web_user where user_name like ‘悟%‘ DEBUG [main] - ==> Parameters:
由此可以看出#和$的区别
#会将字符串进行预处理,用一对引号加在字符串外边,再替代?如#{user_name}% -->‘悟‘%,所以直接用#{}接值控制台报错的原因就在于此。
$将取到的数据直接替换掉,并不会进行预处理。如‘${_parameter}%‘ -->‘悟%‘
三 在映射文件用方法进行拼接
在业务层不进行数据处理,在映射文件调用MySql的concat(param1,param2,...)进行拼接
<select id="where03" resultType="self.exercise.bean.User" parameterType="string"> select * from web_user where user_name like concat(#{user_name},"%") </select>
日志:
DEBUG [main] - ==> Preparing: select * from web_user where user_name like concat(?,"%") DEBUG [main] - ==> Parameters: 悟(String)
针对多条件的where语句
当有多个查询条件时,也有几种方式可以实现。
一 用if标签进行条件筛选 如
//接口中的方法为List<User> wheremore(@Param("userName") String user_name, @Param("account") String account);try { sqlSession = MyBatisUtil.getSqlSession(); String user_name = "悟"; String account = "wukong"; List<User> list = sqlSession.getMapper(UserDao.class).wheremore(user_name, account); logger.debug(list); } finally { MyBatisUtil.closeSqlSession(sqlSession); }
映射文件中的内容为:
<select id="wheremore" resultType="self.exercise.bean.User"> select * from web_user where 1=1 <if test="userName != null and userName != ‘‘.trim()"> and user_name like concat(#{userName},"%") </if> <if test="account != null and account != ‘‘.trim()"> and account = #{account} </if> </select>
其中,test中的变量对应的为map中的key值、类中的属性名或者接口中param方法映射出的属性名
test中进行测试时一些运算符需要进行用转义运算符替换,现整理一些我知道的:
逻辑与 and && 大于 > > 小于 只能用< 等于 ==
判断一个字符串不为空串的几种方式:
<if test="user_name != ‘‘.trim()"></if> <if test="user_name.lengh() != 0"></if>
以上的多条件查询方法,where后面跟着 1=1,每次执行sql语句都会进行一次判断(即使条件全部为空),当数据量很大时效率低下,可以where标签进行改进。
<select id="wheremore02" resultType="self.exercise.bean.User"> select * from web_user <where> <if test="userName != null and userName != ‘‘.trim()"> and user_name like concat(#{userName},"%") </if> <if test="account != null && account.length() != 0"> and account = #{account} </if> </where> </select>
where标签会检索语句,将where中的第一个and 或者or 去掉,这里的and 和or 都是sql中的关键字,如果名为and_user_name的属性在最前面,则不会被检索出来。
二 用choose标签,相当于Java中的switch分支语句
<select id="wheremore03" resultType="self.exercise.bean.User"> select * from web_user <where> <choose> <when test="userName != null and userName != ‘‘.trim()"> and user_name like concat(#{userName},"%") </when> <when test="account != null && account.length() != 0"> and account = #{account} </when> </choose> </where> </select>