Mybatis#与$的区别与认知

最近适用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 [[email protected]] 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 [[email protected]]]
[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相关数据,得知特殊字串的替换与处理问题,
mybatis中#与$的区别:#{} 在动态解析的时候, 会解析成一个参数标记符。${}在动态解析的时候,会将我们传入的参数当做String字符串填充到我们的语句中
  • #方式能够很大程度防止sql注入。
  • $方式无法防止Sql注入。
  • $方式一般用于传入数据库对象,例如传入表名.
本次查询条件中包含特殊字符,我一开始使用的是#,所以会导致查询失败,改为$后查询就成功了。
[2018-04-18 15:21:11,633] [DEBUG] [org.mybatis.spring.transaction.SpringManagedTransaction.openConnection(SpringManagedTransaction.java:87)] [JDBC Connection [[email protected]] 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 [[email protected]]]
[2018-04-18 15:21:11,850] [DEBUG] [org.springframework.jdbc.datasource.DataSourceUtils.doReleaseConnection(DataSourceUtils.java:329)] [Returning JDBC Connection to DataSource]
7