iBatis 中 Like 的写法实现模糊查询

合集下载

iBatis 中 Like 的写法实现模糊查询

iBatis 中 Like 的写法实现模糊查询

iBatis 开发指南告诉我们,当Person 对象的name 属性不为null 时启用name 查询条件在映射文件person.xml 中的配置为<select id="getPersonsByName" resultClass="com.unmi.Person">select id as id,name as name,passwd as passwd from person<dynamic prepend="WHERE"><isNotNull prepend="AND" property="name">(name like #name#)</isNotNull></dynamic></select>再用如下的代码调用Person person = new Person();person.setName("unmi");List list = sqlMap.queryForList("getPersonsByName", person);执行效果翻译成sql 语句就是select * from person where name like 'unmi'select * from person where name like 'unmi'这实际上是一个完全匹配的查询,与用等号写成如下语句是一致的select * from person where name = 'unmi'select * from person where name = 'unmi'我们之所以要用like 谓词,一般都想实现模糊查询,比如说name 以'unmi' 开始、结束或包含'unmi' 的记录,如下select * from person where name like 'unmi%';select * from person where name like '%unmi';select * from person where name like '%unmi%';也就是如上的like 语义在person.xml中应该怎么表述呢?我曾经是想当然的尝试把(name like #name#) 写成(name like '%#name#%') 或(name like %#name#%) ,都没法通过,分别报错java.sql.SQLException: Invalid argument in JDBC call: parameter index out of range: 1和java.sql.SQLException: Unexpected token: % in statement [ select id......那么正确的写法是什么呢?在网上找到一个解答方法有两种:1. 是把上面(name like '%#name#%') 的# 换成$, 也就是(name like '%$name$%')2. 是用|| 连接字符串的方式,写成(name like '%' || #name# || '%')但却不能写成(name like '%'||$name$||'%') ,不能又要出错java.sql.SQLException: Column not found: UNMI in statement [select id......总结一下,在iBatis 中用like 的模糊查询的配置如下(两种方式)<select id="getPersonsByName" resultClass="com.unmi.Person">select id as id,name as name,passwd as passwd from person<dynamic prepend="WHERE"><isNotNull prepend="AND" property="name">(name like '%$name$%')<!-- (name like '%'||#name#||'%') --></isNotNull></dynamic></select>不知细心的诸位注意到没有,这同时也是我在组织上面文字时产生的疑问:1. 写成(name like '%'||$name$||'%') 为什就不行呢?# 和$ 有什么区别呢?2. 还有明明是写成的unmi,为什么报错的时候又是全大写的UNMI 呢?具体的异同我们可能还需从源代码中找,简单的只要知道,$name$ 是字面意义的替换,这种形式要注意SQL 注入的漏洞;#name# 是带类型的替换。

mybatis使用动态sql模糊查询写法

mybatis使用动态sql模糊查询写法

mybatis使用动态sql模糊查询写法1. 引言1.1 概述本文旨在介绍使用MyBatis进行动态SQL模糊查询的写法。

随着互联网技术的发展和数据量的增加,对数据库的模糊查询需求也越来越多。

而动态SQL是MyBatis框架提供的一种强大的查询特性,可以根据不同条件生成相应的SQL 语句,非常适用于模糊查询场景。

1.2 文章结构本文共包括五个部分。

首先,我们会简要介绍MyBatis动态SQL的概念及其作用;接着,详细介绍了动态SQL语句的分类。

然后,重点围绕动态SQL模糊查询展开讲解,包括使用like关键字和concat函数进行模糊查询两种常见写法。

之后,在示例与解析部分,我们将分别给出三个实际案例来演示如何使用动态SQL进行模糊查询,并进行详尽解析。

最后,我们将在结论与总结部分回顾文章内容,并对MyBatis动态SQL的优势和应用场景进行总结。

1.3 目的通过本文,读者将能够全面掌握使用MyBatis进行动态SQL模糊查询的写法,并了解到其在实际开发中的应用。

同时,本文还旨在引导读者深入了解MyBatis 框架的核心特性和灵活查询的技巧,从而提升数据库模糊查询的效率和准确性。

对于开发人员而言,这将是一篇实用且具有指导意义的文章。

2. MyBatis动态SQL概述2.1 MyBatis简介MyBatis是一个开源的持久化框架,它可以将数据库和Java对象之间的映射关系进行配置,并通过XML或注解方式实现对数据库的访问。

MyBatis提供了丰富的功能和灵活性,使得开发者能够更加方便地进行数据持久化操作。

2.2 动态SQL的作用动态SQL是MyBatis中一项非常重要的特性。

它允许我们根据不同条件来动态生成SQL语句,在遇到不同情况时执行不同的数据库操作。

这样可以大大提升程序的灵活性和可维护性。

2.3 动态SQL语句的分类在MyBatis中,动态SQL语句主要分为四类:- if判断:通过if标签来判断某个条件是否成立,根据条件结果来决定是否包含某部分SQL语句。

MyBatisPlus之like模糊查询中包含有特殊字符(_、、%)

MyBatisPlus之like模糊查询中包含有特殊字符(_、、%)

MyBatisPlus之like模糊查询中包含有特殊字符(_、、%)传统的解决思路:⾃定义⼀个拦截器,当有模糊查询时,模糊查询的关键字中包含有上述特殊字符时,在该特殊字符前添加\进⾏转义处理。

新的解决思路:将like 替换为 MySQL内置函数locate函数参考博客:⼀、问题提出使⽤MyBatis中的模糊查询时,当查询关键字中包括有_、\、%时,查询关键字失效。

⼆、问题分析1、当like中包含_时,查询仍为全部,即like '%_%'查询出来的结果与like '%%'⼀致,并不能查询出实际字段中包含有_特殊字符的结果条⽬2、like中包括%时,与1中相同3、like中包含\时,带⼊查询时,%\%⽆法查询到包含字段中有\的条⽬特殊字符未处理处理后_like '%_%'like '%\_%'%like '%%%'like '%\%%'\like '%\%'`like '%\%'ESCAPE '/'必须加在SQL的最后。

like '%\_%'效果与like concat('%', '\_', '%')相同三、问题解决1、⾃定义拦截器⽅法类import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.keyidea.boss.utils.EscapeUtil;import org.apache.ibatis.executor.Executor;import org.apache.ibatis.mapping.BoundSql;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.plugin.*;import org.apache.ibatis.session.ResultHandler;import org.apache.ibatis.session.RowBounds;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.util.HashMap;import java.util.HashSet;import java.util.Properties;import java.util.Set;/*** ⾃定义拦截器⽅法,处理模糊查询中包含特殊字符(_、%、\)*/@Intercepts(@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class,RowBounds.class, ResultHandler.class}))public class MyInterceptor implements Interceptor {Logger LOGGER = LoggerFactory.getLogger(MyInterceptor.class);@Overridepublic Object intercept(Invocation invocation) throws Throwable {// 拦截sqlObject[] args = invocation.getArgs();MappedStatement statement = (MappedStatement)args[0];Object parameterObject = args[1];BoundSql boundSql = statement.getBoundSql(parameterObject);String sql = boundSql.getSql();// 处理特殊字符modifyLikeSql(sql, parameterObject, boundSql);// 返回return invocation.proceed();}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {}@SuppressWarnings("unchecked")public static String modifyLikeSql(String sql, Object parameterObject, BoundSql boundSql) {if (parameterObject instanceof HashMap) {} else {return sql;}if (!sql.toLowerCase().contains(" like ") || !sql.toLowerCase().contains("?")) {return sql;}// 获取关键字的个数(去重)String[] strList = sql.split("\\?");Set<String> keyNames = new HashSet<>();for (int i = 0; i < strList.length; i++) {if (strList[i].toLowerCase().contains(" like ")) {String keyName = boundSql.getParameterMappings().get(i).getProperty();keyNames.add(keyName);}}// 对关键字进⾏特殊字符“清洗”,如果有特殊字符的,在特殊字符前添加转义字符(\)for (String keyName : keyNames) {HashMap parameter = (HashMap)parameterObject;if (keyName.contains("ew.paramNameValuePairs.") && sql.toLowerCase().contains(" like ?")) {// 第⼀种情况:在业务层进⾏条件构造产⽣的模糊查询关键字QueryWrapper wrapper = (QueryWrapper)parameter.get("ew");parameter = (HashMap)wrapper.getParamNameValuePairs();String[] keyList = keyName.split("\\.");// ew.paramNameValuePairs.MPGENVAL1,截取字符串之后,获取第三个,即为参数名Object a = parameter.get(keyList[2]);if (a instanceof String && (a.toString().contains("_") || a.toString().contains("\\") || a.toString().contains("%"))) {parameter.put(keyList[2],"%" + EscapeUtil.escapeChar(a.toString().substring(1, a.toString().length() - 1)) + "%");}} else if (!keyName.contains("ew.paramNameValuePairs.") && sql.toLowerCase().contains(" like ?")) { // 第⼆种情况:未使⽤条件构造器,但是在service层进⾏了查询关键字与模糊查询符`%`⼿动拼接 Object a = parameter.get(keyName);if (a instanceof String && (a.toString().contains("_") || a.toString().contains("\\") || a.toString().contains("%"))) {parameter.put(keyName,"%" + EscapeUtil.escapeChar(a.toString().substring(1, a.toString().length() - 1)) + "%");}} else {// 第三种情况:在Mapper类的注解SQL中进⾏了模糊查询的拼接Object a = parameter.get(keyName);if (a instanceof String && (a.toString().contains("_") || a.toString().contains("\\") || a.toString().contains("%"))) {parameter.put(keyName, EscapeUtil.escapeChar(a.toString()));}}}return sql;}}2、在配置类中添加⾃定义拦截器import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties;import com.baomidou.mybatisplus.core.config.GlobalConfig;import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;import org.apache.ibatis.plugin.Interceptor;import org.apache.ibatis.session.SqlSessionFactory;import org.mybatis.spring.annotation.MapperScan;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Primary;import org.springframework.jdbc.datasource.DataSourceTransactionManager;import javax.sql.DataSource;import java.util.ArrayList;import java.util.List;/*** MyBatis配置数据源、sqlSessionFactory、事务管理器、分页插件、⾃定义拦截器等*/@Configuration@MapperScan(basePackages = {"com.keyidea.boss.mapper"}, sqlSessionFactoryRef = "masterSqlSessionFactory")public class MybatisPlusConfig {@Autowiredprivate MybatisPlusProperties properties;// 使⽤MyBatis中的分页插件@Beanpublic PaginationInterceptor paginationInterceptor() {PaginationInterceptor page = new PaginationInterceptor();return page;}// ⾃定义拦截器实现模糊查询中的特殊字符处理@Beanpublic MyInterceptor myInterceptor() {MyInterceptor sql = new MyInterceptor();return sql;}// 数据源配置@Bean(name = "masterDataSource")@ConfigurationProperties("spring.datasource")@Primarypublic DataSource masterDataSource() {return DruidDataSourceBuilder.create().build();}// 配置sqlSessionFactory@Bean(name = "masterSqlSessionFactory")@Primarypublic SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource,PaginationInterceptor paginationInterceptor, MyInterceptor myInterceptor) throws Exception {final MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();sessionFactory.setDataSource(dataSource);if (this.properties.getConfigurationProperties() != null) {sessionFactory.setConfigurationProperties(this.properties.getConfigurationProperties());}GlobalConfig globalConfig = this.properties.getGlobalConfig();sessionFactory.setGlobalConfig(globalConfig);// 设置MyBatis的插件/拦截器列表List<Interceptor> interceptors = new ArrayList<>();interceptors.add(paginationInterceptor);interceptors.add(myInterceptor);sessionFactory.setPlugins(interceptors.toArray(new Interceptor[1]));return sessionFactory.getObject();}// 设置事务管理器,在需要事务的service层使⽤如下注解进⾏事务管理// @Transactional(transactionManager = "masterTransactionManager", rollbackFor = Exception.class)@Bean(name = "masterTransactionManager")public DataSourceTransactionManager masterTransactionManager(@Qualifier("masterDataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}}由于框架中使⽤多个数据源配置,因此使⽤数据库事务时,优先使⽤该事务时,需要在该⽅法上显著的添加@Primary注解3、⼯具类:特殊字符转义import ng3.StringUtils;public class EscapeUtil {//mysql的模糊查询时特殊字符转义public static String escapeChar(String before){if(StringUtils.isNotBlank(before)){before = before.replaceAll("\\\\", "\\\\\\\\");before = before.replaceAll("_", "\\\\_");before = before.replaceAll("%", "\\\\%");}return before ;}}4、引⼊依赖包,以下为参考项build.gradle⽂件中的依赖如下dependencies {implementation 'org.springframework.boot:spring-boot-starter-web'testImplementation 'org.springframework.boot:spring-boot-starter-test'implementation 'org.springframework.boot:spring-boot-starter-aop'implementation 'com.baomidou:mybatis-plus-boot-starter:3.1.0'implementation 'com.alibaba:druid-spring-boot-starter:1.1.10'implementation 'mysql:mysql-connector-java'implementation 'mons:commons-lang3:3.4'implementation 'org.jeecg:easypoi-base:2.1.3'implementation 'org.jeecg:easypoi-annotation:2.1.3'implementation 'org.springframework.boot:spring-boot-starter-mail'compile 'org.apache.httpcomponents:httpclient:4.3.1'compile 'net.sf.json-lib:json-lib:2.4:jdk15'}四、重点关注以上⽅法在关键字中包含有\可能会失效,失效的原因是由于查询的关键字的数据库字段排序规则为utf8_unicode_ci,如下图字段排序规则为:utf8_unicode_ci要想不失效,查询的关键字的排序规则必须为utf8_general_ci,如下图字段排序规则为:utf8_general_ci或者统⼀全部数据库字符集与排序规则分别为:utf8mb4与utf8mb4_general_ci,如下图字段排序规则为:utf8mb4_general_ci【END】。

like模糊查询

like模糊查询

like模糊查询本章节将介绍 like、notLike、likeRight、likeLeft 条件,like(完全模糊,即“like '%val%'”)1 2like(R column, Object val)like(boolean condition, R column, Object val)参数说明:column:要⽤于条件筛选的数据库表列名称,如:nameval:⽤于指定数据表列的值,条件将根据该值进⾏筛选condition:⽤于指定当前这个条件是否有效;如果为 true,则应⽤当前条件;如果为 false,则忽略当前条件。

实例:查询⽤户名称中包含“王”值的⽤户信息,如下:1 2QueryWrapper<UserBean> wrapper = new QueryWrapper<>(); wrapper.like("name", "王"); // 等价 SQL 语句:name like '%王%'notLike(完全模糊取⾮,即“not like '%val%'”)1 2notLike(R column, Object val)notLike(boolean condition, R column, Object val)参数说明:column:要⽤于条件筛选的数据库表列名称,如:nameval:⽤于指定数据表列的值,条件将根据该值进⾏筛选condition:⽤于指定当前这个条件是否有效;如果为 true,则应⽤当前条件;如果为 false,则忽略当前条件。

实例:查询⽤户包含“王”值的⽤户信息,如下:1 2QueryWrapper<UserBean> wrapper = new QueryWrapper<>(); wrapper.notLike("name", "王"); // 等价 SQL 语句:name not like '%王%'likeLeft(仅左边模糊,即“like '%val'”)1 2likeLeft(R column, Object val)likeLeft(boolean condition, R column, Object val)参数说明:column:要⽤于条件筛选的数据库表列名称,如:nameval:⽤于指定数据表列的值,条件将根据该值进⾏筛选condition:⽤于指定当前这个条件是否有效;如果为 true,则应⽤当前条件;如果为 false,则忽略当前条件。

Mybatis中Like的使用方式以及一些注意点

Mybatis中Like的使用方式以及一些注意点

Mybatis中Like的使⽤⽅式以及⼀些注意点做⼀个积极的⼈编码、改bug、提升⾃⼰我有⼀个乐园,⾯向编程,春暖花开!模糊查询在项⽬中还是经常使⽤的,本⽂就简单整理Mybatis中使⽤Like进⾏模糊查询的⼏种写法以及⼀些常见的问题。

使⽤Springboot简单配置⼀下Mybatis,然后进⾏说明。

Springboot集成Mybatis这⾥就不做介绍了。

初始数据⽅式⼀在Mybatis中的第⼀种写法:<!--有sql注⼊问题--><select id="findUserByLikeName1" parameterType="ng.String" resultMap="user">select * from t_user where name like '%${name}%'</select>这种会有sql注⼊的问题,需要明⽩在 Mybatis中$和#使⽤的区别。

这种写法也不能加jdbcType=VARCHAR,否则也会报错。

做了个简单的测试:@Testpublic void findUserByLikeName1(){List<User> test = userMapper.findUserByLikeName1("Cloud");//select * from t_user where name like '%Cloud%'System.out.println(test.size());// 查出⼀条List<User> test1 = userMapper.findUserByLikeName1("' or '1=1");//select * from t_user where name like '%' or '1=1%'// 分析: '1=1%' 成⽴System.out.println(test1.size());// 查出了全部数据}注意:排序的字段也容易出现这个问题,在使⽤的时候也⼀定要注意。

mysql模糊查询like反向写法

mysql模糊查询like反向写法

mysql模糊查询like反向写法
在MySQL中,模糊查询使用`LIKE`关键字,可以通过将搜索条件反向写入`LIKE`子句来实现反向模糊查询。

通常,我们使用`%`表示零个或多个字符的通配符。

如果要查找包含特定字符串的字段,可以使用以下方式:
```sql
SELECT column_name
FROM table_name
WHERE column_name LIKE '%search_string%';
```
这将匹配包含`search_string`的任何字段值。

例如,如果我们搜索包含"apple" 的字段,它将匹配"pineapple," "applesauce," "crabapple," 等等。

现在,如果你想进行反向模糊查询,即查找不包含特定字符串的字段,你可以使用以下方式:
```sql
SELECT column_name
FROM table_name
WHERE column_name NOT LIKE '%search_string%';
```
这将返回不包含`search_string`的任何字段值。

请注意,反向模糊查询可能会导致较慢的查询性能,因为数据库引擎需要扫描整个表来查找匹配项。

如果可能的话,尽量使用正向模糊查询来提高查询效率。

ibatis的模糊查询

ibatis的模糊查询

ibatis的模糊查询this.getSqlMapClientTemplate().queryForList("getAllUserModel", dto); 我传的参数是一个封装的DTO类。

传入后用dto类把参数给sql语句赋值。

其中发生的第一个问题是<isGreaterThan prepend=" and " property="createTime"comparue="2008/01/01 00:00:00"></isGreaterThan>必须要付给它默认的comparue值。

后来有看到了ibatis的其他属性。

还得仔细研究好好琢磨才行。

<!-- 测试模糊查询 --><select id="getAllUserModel" parameterClass="UserModelDto" resultClass="UserModelDto">selectTEMPLATEID,USERID,TEMPLATENAME,CREATETIME,ENABLED,TEMPLATEDESCRIPTION,REMARKfrom TBTEMPLATE<dynamic prepend="WHERE"><!-- isNotNull判断参数是否存在,Integer类型 --><isNotNull property="templateID"><!-- isGreaterThan判断参数是否大于comparue,isGreaterEquals是大于等于 --><isGreaterThan prepend=" and " property="templateID" comparue="10001">TEMPLATEID = #templateID#</isGreaterThan></isNotNull><isNotEmpty prepend=" and " property="templateName">TEMPLATENAME like '%$templateName$%'</isNotEmpty><isNotEmpty prepend=" and " property="userID"> <!-- isNotEmpty判断字串不为空,isEmpty可以判断字串为空 -->USERID like '%$userID$%'<!-- 模糊查询不能用#,#在是用prepareStatement的?插入参数,$是文本替换 --></isNotEmpty><isNotNull property="createTime"><isGreaterThan prepend=" and " property="createTime" comparue="2008/01/01 00:00:00">CREATETIME = #createTime#</isGreaterThan></isNotNull><isEqual prepend=" and " property="enabled" comparue="1"> ENABLED = $enabled$</isEqual><!-- 判断相等 --></dynamic></select>。

SQL之模糊查询的四种用法

SQL之模糊查询的四种用法

SQL之模糊查询的四种用法MySql 使用 like关键字进行模糊查询,like关键字通常用在 where条件查询,like关键字通常配合 %、_、[ ]、[^ ] 使用。

一、%%表示任意0个或多个字符。

可匹配任意类型和长度的字符,有些情况下若是中文,请使用两个百分号(%%)表示。

1、所查询字段 + like '%深%'//把含有“深”字的 FName字段出来 select * from T_OM_Institution where FName li ke '%深%'注意:只能查询连续的文字。

【比如“深圳市福田区”可以查询,“深圳市区”查询不出来】2、所查询字段 + like '%深%' and 所查询字段 + like '%福%'//把含有“深”字、“福”字的 FName字段出来 select * from T_OM_Institution where FName like '%深%' and FName like '%福%'注意:此语句没有那么灵活,比较适用于固定的一些文字的查询。

3、所查询字段 + like '%深%福%小%'//把含有“深”字、“福”字、“小”字的 FName字段出来 select * from T_OM_Institutio n where FName like '%深%' and FName like '%深%福%小%'注意:此语句比较灵活,可以查询相隔几个文字,比较实用。

【比如“深圳市福田区小学”可以查询,“深圳市福区小”也可以查询】二、_表示任意单个字符。

匹配单个任意字符,它常用来限制表达式的字符长度语句。

1、查询出中间含有“小”字的FRealName字段(前提:名字三个字)select * from T_UM_User where FRealName like '_小_' //只能查询出类似“唐小一”这样的FRealName为三个字且中间一个字为:“小”2、查询出姓“唐”的姓名(前提:名字三个字)select * from T_UM_User where FRealName like '唐__' //唐__:后面有两横杠 //查询出姓“唐”的FRealName,且FRealName的字数必须为33、查询名字最后一个字为“西”的姓名(前提:名字三个字)select * from T_UM_User where FRealName like '__西' //__西:前面有两横杠 //查询出姓名最后一个字为“西”的姓名,且FRealName的字数必须为3图64-1、查询出姓“文”的姓名(前提:名字两个字)select * from T_UM_User where FRealName like '文_' //文_:后面只有一横杠图74-2、查询出姓“唐”的姓名(前提:名字两个字或三个字)select * from T_UM_User where FRealName like '%唐_%' //唐_:后面只有一横杠 //查询出来的姓名可以是两个字,也可以是三个字图85-1、查询名字最后一个字为“亮”的姓名(前提:名字两个字)select * from T_UM_User where FRealName like '_亮'图95-2、查询名字最后一个字为“师”的姓名(前提:名字两个字或三个字)select * from T_UM_User where FRealName like '%_师%' //查询出来的姓名可以是两个字,也可以是三个字三、[ ] -> 语句执行之后没反应表示括号内所列字符中的一个(类似正则表达式)。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

iBatis 开发指南告诉我们,当Person 对象的name 属性不为null 时启用name 查询条件在映射文件person.xml 中的配置为
<select id="getPersonsByName" resultClass="com.unmi.Person">
select id as id,name as name,passwd as passwd from person
<dynamic prepend="WHERE">
<isNotNull prepend="AND" property="name">
(name like #name#)
</isNotNull>
</dynamic>
</select>
再用如下的代码调用
Person person = new Person();
person.setName("unmi");
List list = sqlMap.queryForList("getPersonsByName", person);
执行效果翻译成sql 语句就是
select * from person where name like 'unmi'
select * from person where name like 'unmi'
这实际上是一个完全匹配的查询,与用等号写成如下语句是一致的
select * from person where name = 'unmi'
select * from person where name = 'unmi'
我们之所以要用like 谓词,一般都想实现模糊查询,比如说name 以'unmi' 开始、结束或包含'unmi' 的记录,如下
select * from person where name like 'unmi%';
select * from person where name like '%unmi';
select * from person where name like '%unmi%';
也就是如上的like 语义在person.xml中应该怎么表述呢?我曾经是想当然的尝试把(name like #name#) 写成(name like '%#name#%') 或(name like %#name#%) ,都没法通过,分别报错
java.sql.SQLException: Invalid argument in JDBC call: parameter index out of range: 1

java.sql.SQLException: Unexpected token: % in statement [ select id......
那么正确的写法是什么呢?在网上找到一个解答方法有两种:
1. 是把上面(name like '%#name#%') 的# 换成$, 也就是(name like '%$name$%')
2. 是用|| 连接字符串的方式,写成(name like '%' || #name# || '%')
但却不能写成(name like '%'||$name$||'%') ,不能又要出错
java.sql.SQLException: Column not found: UNMI in statement [select id......
总结一下,在iBatis 中用like 的模糊查询的配置如下(两种方式)
<select id="getPersonsByName" resultClass="com.unmi.Person">
select id as id,name as name,passwd as passwd from person
<dynamic prepend="WHERE">
<isNotNull prepend="AND" property="name">
(name like '%$name$%')
<!-- (name like '%'||#name#||'%') -->
</isNotNull>
</dynamic>
</select>
不知细心的诸位注意到没有,这同时也是我在组织上面文字时产生的疑问:
1. 写成(name like '%'||$name$||'%') 为什就不行呢?# 和$ 有什么区别呢?
2. 还有明明是写成的unmi,为什么报错的时候又是全大写的UNMI 呢?
具体的异同我们可能还需从源代码中找,简单的只要知道,$name$ 是字面意义的替换,这种形式要注意SQL 注入的漏洞;#name# 是带类型的替换。

至于unmi被转换成大写,还需再研究研究,对于以上两个疑问必要时还可以发挥一下。

也要权衡一下花那个时间值不值。

附:
为了防止SQL注入,iBatis模糊查询时也要避免使用
$$来进行传值。

下面是三个不同数据库的ibatis的模糊查询传值。

mysql: select * from stu where name like concat('%',#name #,'%')
oracle: select * from stu where name like '%'||#name #||'%'
SQL Server:select * from stu where name like '%'+#name #+'%。

相关文档
最新文档