mybatis字符#与字符$的区别
问题:使用in查询查询出一批数据,in查询的参数是字符串拼接的。调试过程中,把mybatis输出的sql复制到navicat中,在控制台将sql的参数也复制出来,替换到sql的字符 '?' 的位置,执行sql,能查询到数据,但是java程序无法查询到数据。
原因:因为mybatis的参数占位符以#字符开头的参数,在处理过程中会自动给参数加引号,及一些字符过滤处理(例如防止sql注入等等)
解决方式: in查询的参数占位符换成字符$开头,因为mybatis在处理 $ 开头的参数占位符时候不会给参数加引号及其他额外处理(例如sql注入字符过滤),使用的是参数原值。
mybatis 参数查询修改前片段
AND a.source in (#{source}) mybatis 参数查询修改后片段
AND a.source in (${source})
其他: 因为mybatis的参数占位符以#字符开头的参数,在处理过程中会自动给参数加引号,那么是加单引号还是双引号呢?
实际上mybatis对这个#开头的参数参数进行了参数化处理,防止注入。
如果参数拼接 top_news','net_music','knowledge_sns','wb ,如果#开头参数处理是单纯加单引号,那么sql条件语句如果变成如下这样,是可以查询到数据的,但是结果是没有查询到数据,说明,时间拼接的数据不是如下的结果,结果是#开头的参数不是单纯的加单引号处理
AND a.source in ('top_news','net_music','knowledge_sns','wb')
如果参数拼接使用双引号拼接如下 top_news","net_music","knowledge_sns","wb ,如果#开头参数处理是单纯加双引号,那么sql条件语句如果变成如下这样,是可以查询到数据的,但是结果是没有查询到数据,说明,实际拼接的数据不是如下的结果,结果是#开头的参数不是单纯的加双引号处理
AND a.source in ("top_news","net_music","knowledge_sns","wb")
至于#开头的参数到底怎么处理的,既不是单纯加单引号也不是单纯加双引号,具体做了哪些处理,请阅读源码。反正mybatis进行in查询时,参数是拼接好的字符串的时候,参数占位符使用$,而不使用#,在使用$做参数占位符时候,给参数赋值前确保代码里做了防注入处理或者已知的代码是安全的不存在sql注入的,可以直接使用$作为参数占位符。
mybatis xml 文件(修改前),in查询参数使用占位符使用字符#
![](https://common.cnblogs.com/images/copycode.gif)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.thinkgem.jeesite.modules.backend.dao.ChannelDao">
<sql id="channelColumns">
a.id AS "id",
a.name AS "name",
a.source AS "source",
a.url AS "url",
a.create_by AS "createBy.id",
a.update_by AS "updateBy.id",
a.update_date AS "updateDate",
a.create_date AS "createDate",
a.remarks AS "remarks",
a.del_flag AS "delFlag"
</sql> <sql id="channelJoins">
</sql> <select id="findList" resultType="Channel">
SELECT
<include refid="channelColumns"/>
FROM mkt_channel a
<include refid="channelJoins"/>
<where>
a.del_flag = #{DEL_FLAG_NORMAL}
<if test="source != null and source!=''">
AND a.source in (#{source})
</if> <if test="createBy != null">
AND a.create_by = #{createBy.id}
</if> </where>
<choose>
<when test="page !=null and page.orderBy != null and page.orderBy != ''">
ORDER BY ${page.orderBy}
</when>
<otherwise>
ORDER BY a.update_date DESC
</otherwise>
</choose>
</select>
</mapper>
![](https://common.cnblogs.com/images/copycode.gif)
ChannelController.java
![](https://common.cnblogs.com/images/copycode.gif)
@Controller
@RequestMapping(value = "${a}/backend/channel")
public class ChannelController extends BaseController { @Autowired
private ChannelService channelService; @Autowired
private SystemService systemService; @RequiresPermissions("backend:channel:view")
@RequestMapping(value = {"list", ""})
public String list(Channel channel, HttpServletRequest request, HttpServletResponse response, Model model) { String sourceName= request.getParameter("sourceName");
String srcStr = null;
boolean srcFindDo = false;
if(StringUtils.isNotEmpty(sourceName)) {
Map<String, Object> findedChannelMap = SourceUtils.getInstance().searchSourceList(sourceName);
srcStr = (String) findedChannelMap.get("srcStr");
srcFindDo = true;
} String createBy = request.getParameter("createBy");
channel.setCreateBy(null);
createBy = XssFilter.getInstance().cleanXssChars(createBy);
if(StringUtils.isNotEmpty(createBy)) {
User user = systemService.getUserById(createBy);
if(null != user) {
channel.setCreateBy(user);
}
} Page<Channel> page = new Page<>(); if(srcFindDo && StringUtils.isEmpty(srcStr)){
page.setList(new ArrayList<>());
page.setPageNo(0);
page.setPageSize(0);
page.setCount(0);
page.setMessage("没有找到数据");
}
else {
channel.setUtmSource(labelStr);
page = channelService.findPage(new Page<Channel>(request, response), channel);
} model.addAttribute("page", page);
return "modules/backend/channelList";
}
}
![](https://common.cnblogs.com/images/copycode.gif)
SourceUtils.java
![](https://common.cnblogs.com/images/copycode.gif)
package com.thinkgem.jeesite.common.utils; import com.thinkgem.jeesite.modules.backend.entity.ChannelSource;
import com.thinkgem.jeesite.modules.sys.entity.Dict;
import com.thinkgem.jeesite.modules.sys.utils.DictUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.*; public class SourceUtils { private Logger logger = LogManager.getLogger(SourceUtils.class); private ChannelSourceFacade channelSourceFacade; private static SourceUtils instance; private SourceUtils() {
channelSourceFacade = SpringContextHolder.getBean(ChannelSourceFacade.class);
} public static SourceUtils getInstance() {
if (null == instance) {
instance = new SourceUtils();
}
return instance;
} /**
* 获取所有的来源列表
* @return
*/
public List<ChannelSource> getAllSource() {
List<ChannelSource> dataList = new ArrayList<>();
Response<List<ChannelSource>> response = channelSourceFacade.getChannelSourceList();
dataList = response.getData();
return dataList;
} /**
* 根据来源名称模糊查找渠道
* @return
*/
public Map<String,Object> searchChannelList(String label,String desc,String code) {
Map<String,Object> dictMap = new HashMap<>();
String labelStr = "";
List<ChannelSource> findedList = new ArrayList<>();
List<ChannelSource> srcList = getAllChannelDict();
if(null != srcList && srcList.size() > 0) {
for (ChannelSource item : srcList) {
if (dictMap.containsKey(item.getLabel())) {
continue;
}
if(channelMatch(name,item)) {
findedList.add(item);
srcStr = String.format("%s'%s',",srcStr,item.getLabel());
}
}
}
if(srcStr.length() > 1) {
//移除最后一个逗号和2个引号
srcStr = srcStr.substring(0, srcStr.length() - 1);
}
dictMap.put("srcStr",srcStr);
dictMap.put("findedList",findedList);
return dictMap;
} private boolean channelMatch(String sourceName,Dict item) {
boolean result = true;
name = null == name ? "" : name;
if (StringUtils.isNotEmpty(name)) {
if (dict.getDescription().indexOf(desc) == -1) {
result = false;
return result;
}
}
return result;
} }
![](https://common.cnblogs.com/images/copycode.gif)
mybatis字符#与字符$的区别的更多相关文章
- Spring Data JPA、MyBatis还有Hibernate有什么区别
原文:https://www.imooc.com/article/19754?block_id=tuijian_wz Spring Data JPA.MyBatis还有Hibernate有什么区别 2 ...
- Mybatis中的#与$的区别
一.对比场景 场景:数据库分表时,需要将分表的表序号传入的sql中. SpringBoot中使用注解如下: @Insert("insert into collect_#{tblNum}(id ...
- 【mybatis】mybatis中 的# 和 $的区别
mybatis中 的# 和 $的区别 参考地址:https://www.cnblogs.com/sxdcgaq8080/p/10869144.html
- Mybatis和Hibernate框架的区别
Mybatis和Hibernate框架的区别1 简单简介 1.1 Hibernate 框架 Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,建立对象与数据 ...
- mybatis中的#和$的区别 以及 防止sql注入
声明:这是转载的. mybatis中的#和$的区别 1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号.如:order by #user_id#,如果传入的值是111,那么解析成sq ...
- mybatis #号与$号的区别
区别: 在sql中当传入的参数是字符型,则用#号会带上单引号,不会引起sql注入: 在sql中当传入的参数是字符型,则用$号不会带上单引号,会引起sql注入: 使用范围: 当传入的参数用于查询条件,尽 ...
- java用字符写字符
import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.GraphicsEnvir ...
- mybatis中#和$符号的区别
mybatis做为一个轻量级ORM框架在许多项目中使用,因其简单的入门受到了广大开发者的热爱.在近期项目中再做一个相关的开发,碰到了#.$符号这样的问题,之前没怎么注意过,通过学习之后,有了点感悟,分 ...
- FileInputStream(字节流)与fileReader(字符流) 的区别
FileInputStream 类 1 ) FileInputStream 类介绍: 以字节为单位的流处理.字节序列:二进制数据.与编码无关,不存在乱码问题. FileInputStream 类的主要 ...
随机推荐
- 打开App显示文件已损坏,打不开,您应该将它移到废纸篓,怎么办?
1. 首先确保系统安全设置已经改为任何来源 sudo spctl --master-disable 2. 打开任何来源后,到应用程序目录中尝试运行软件,如果仍提示损坏,请在应用图标上,鼠标右键,在弹出 ...
- 使用谷歌提供的SwipeRefreshLayout下拉控件进行下拉刷新的实现数据的刷新
package com.loaderman.swiperefreshdemo; import android.os.Bundle; import android.os.Handler; import ...
- springboot启动报错:Failed to configure a DataSource
一.背景 springboot的出现,让项目搭建变得更方便快捷,同时简化掉很多的样板化配置代码,提高开发效率. 通过idea生成springboot项目,启动报错:Failed to configur ...
- mysql的基本操作命令
1,数据库操作: create database 数据库名 例:create database test; 亦或 create database test charset=utf8; 相关操作: 显示 ...
- Ansible变量嵌套解析
有时候需要用到ansible的变量的嵌套解析,就是“变量中嵌套变量”.例子如下: 假设有一个外部传递的变量,system_code = CRM,而我们同时有一系列类似的变量,如: ABS_port=1 ...
- Spring boot (一):入门篇
Spring boot 简介 Build Anything with Spring Boot:Spring Boot is the starting point for building all Sp ...
- 记录一次MySQL进程崩溃,无法重启故障排查
最近程序在跑着没几天,突然访问不了,查看应用进程都还在.只有数据库的进程down掉了.于是找到日志文件看到如下错误 -- :: [Note] InnoDB: Initializing buffer p ...
- [Python3] 037 函数式编程 装饰器
目录 函数式编程 之 装饰器 Decrator 1. 引子 2. 简介 3. 使用 函数式编程 之 装饰器 Decrator 1. 引子 >>> def func(): ... pr ...
- windows10专业版激活
[1]右击我的电脑->属性,查看激活情况 [2]管理员身份打开CMD [2.1]如果不知道CMD是什么东西 [2.2]如果上面那个也找不到,直接按windows键(就是ctrl和alt中间那个键 ...
- 设计模式在 Spring 框架中的良好应用
在开始正文之前,请你先思考几个问题: 你项目中有使用哪些 GOF 设计模式 说一说 GOF 23 种设计模式的设计理念 说说 Spring 框架中如何实现设计模式 假设我是面试官问起了你这些面试题,你 ...