最近适用mybatis有个查询需求,就是将商品属性与数据库中的商品属性字符串进行比对,从而通过用户筛选的属性获取对应的商品。 从前台获取json封装都1属性值对后,在后台进行解析,然后对多个属性存储在List集合中。然后将该集合传参给Mapper接口进行查询。
其中List集合中的值长这样
List<String> attr = new ArrayList<String>();
attr.add("'%\"品牌\":[%\"花花公子\"%]%'");
attr.add("'%\"尺码\":[%\"M\"%]%'");
mapper接口是这样子搭:
//通过类目id与商品属性获取该类目
List<Good> selectByAttributes(@Param("id")Integer id, @Param("attr")List<String> attr);
然后xml文件查询语句是这样的:
<!--通过类目id与商品属性获取该类目 -->
<select id="selectByAttributes" resultMap="BaseResultMap">
SELECT sg.id,sg.goodName,sg.status,sg.updateTime,sg.enteringTime,sg.updatePersonId,sg.enteringPersonId,sg.romotion,sg.totalSales ,sg.originalPrice
from shop_good sg
LEFT JOIN shop_base_attri_good sbag on sbag.goodId = sg.id
where categoryId = #{id,jdbcType=INTEGER} and
<foreach item="attribute" collection="attr" index="index" separator=" and ">
attributes like #{attribute}
</foreach>
</select>
以上,一切看起来自我感觉良好,测试运行以下,获取的结果是List<Good>的大小为0
一脸懵逼的查看运行日志:
[2018-04-18 15:09:35,700] [DEBUG] [org.mybatis.spring.transaction.SpringManagedTransaction.openConnection(SpringManagedTransaction.java:87)] [JDBC Connection [com.mysql.jdbc.JDBC4Connection@3b718392] will not be managed by Spring]
[2018-04-18 15:09:35,712] [DEBUG] [org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)] [==> Preparing: SELECT sg.id,sg.goodName,sg.status,sg.updateTime,sg.enteringTime,sg.updatePersonId,sg.enteringPersonId,sg.romotion,sg.totalSales ,sg.originalPrice from shop_good sg LEFT JOIN shop_base_attri_good sbag on sbag.goodId = sg.id where categoryId = ? and attributes like ? and attributes like ? ]
[2018-04-18 15:09:35,796] [DEBUG] [org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)] [==> Parameters: 64(Integer), '%"品牌":[%"花花公子"%]%'(String), '%"尺码":[%"M"%]%'(String)]
[2018-04-18 15:09:35,854] [DEBUG] [org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)] [<== Total: 0]
[2018-04-18 15:09:35,857] [DEBUG] [org.mybatis.spring.SqlSessionUtils.closeSqlSession(SqlSessionUtils.java:191)] [Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@d816dde]]
[2018-04-18 15:09:35,857] [DEBUG] [org.springframework.jdbc.datasource.DataSourceUtils.doReleaseConnection(DataSourceUtils.java:329)] [Returning JDBC Connection to DataSource]
0
从上面看到查询语句没出错,传参也没错,于是不服的拿到navicat进行查询,结果如下:

于是很纳闷,问题出现在哪里,通过查阅mybatis相关数据,得知特殊字串的替换与处理问题,
mybatis中#与$的区别:#{} 在动态解析的时候, 会解析成一个参数标记符。${}在动态解析的时候,会将我们传入的参数当做String字符串填充到我们的语句中
- #方式能够很大程度防止sql注入。
- $方式无法防止Sql注入。
- $方式一般用于传入数据库对象,例如传入表名.
本次查询条件中包含特殊字符,我一开始使用的是#,所以会导致查询失败,改为$后查询就成功了。
[2018-04-18 15:21:11,633] [DEBUG] [org.mybatis.spring.transaction.SpringManagedTransaction.openConnection(SpringManagedTransaction.java:87)] [JDBC Connection [com.mysql.jdbc.JDBC4Connection@7ee55e70] will not be managed by Spring]
[2018-04-18 15:21:11,651] [DEBUG] [org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)] [==> Preparing: SELECT sg.id,sg.goodName,sg.status,sg.updateTime,sg.enteringTime,sg.updatePersonId,sg.enteringPersonId,sg.romotion,sg.totalSales ,sg.originalPrice from shop_good sg LEFT JOIN shop_base_attri_good sbag on sbag.goodId = sg.id where categoryId = ? and attributes like '%"品牌":[%"花花公子"%]%' and attributes like '%"尺码":[%"M"%]%' ]
[2018-04-18 15:21:11,697] [DEBUG] [org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)] [==> Parameters: 64(Integer)]
[2018-04-18 15:21:11,848] [DEBUG] [org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)] [<== Total: 7]
[2018-04-18 15:21:11,850] [DEBUG] [org.mybatis.spring.SqlSessionUtils.closeSqlSession(SqlSessionUtils.java:191)] [Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@d816dde]]
[2018-04-18 15:21:11,850] [DEBUG] [org.springframework.jdbc.datasource.DataSourceUtils.doReleaseConnection(DataSourceUtils.java:329)] [Returning JDBC Connection to DataSource]
7