最近适用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