java in查询无法查询到数据(mybatis字符#与字符$的区别)

 

 

   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查询参数使用占位符使用字符#

<?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>

ChannelController.java

@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";
    }
}

 

SourceUtils.java

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://www.cnblogs.com/huangzhihua/p/7761136.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在MyBatis中,#{}和${}都是用于传递参数的方式,但它们的处理方式不同。 #{}是预编译处理,将传入的参数按照JDBC规范进行处理,可以防止SQL注入攻击,同时也可以自动进行类型转换。 ${}是字符串替换,将传入的参数直接替换到SQL语句中,不进行预编译处理,可能会存在SQL注入攻击的风险,同时也不会进行类型转换。 因此,一般情况下,建议使用#{}来传递参数,以保证SQL的安全性和可读性。而${}一般用于传递动态表名、列名等情况,需要注意安全性问题。 ### 回答2: MyBatis是一个开源的持久层框架,它主要用于简化JDBC操作和数据库交互。它的设计目标是将SQL语句和Java代码相分离,使得开发人员可以将精力集中在业务逻辑上而不是繁琐的数据库操作上。 MyBatis的核心组件包括:SQL映射文件、SqlSession、SqlSessionFactory和SqlSessionFactoryBuilder。首先,开发人员需要编写SQL映射文件,这个文件定义了数据库表和Java对象之间的映射关系和SQL语句。然后,使用SqlSessionFactoryBuilder来构建一个SqlSessionFactory对象,SqlSessionFactory是例的,它提供了获取SqlSession对象的方法。SqlSession是执行SQL语句的核心,它提供了对数据库的CRUD操作,开发人员可以通过SqlSession的方法来执行SQL语句和获取结果。 在使用MyBatis时,可以通过各种各样的配置来满足不同的需求。例如,可以使用typeAliases来定义Java对象和数据库表之间的映射关系,可以使用resultMaps来自定义复杂查询的结果映射规则,还可以使用动态SQL来根据条件拼接不同的SQL语句。另外,MyBatis还提供了一些特殊功能,例如一级缓存和二级缓存,用于提高查询性能。 总的来说,MyBatis是一个强大且灵活的持久层框架,它可以帮助开发人员简化数据库操作,并提高查询性能。使用MyBatis,开发人员可以专注于业务逻辑的实现,而不需要关注繁琐的数据库操作。 ### 回答3: Mybatis 是一个开源的持久层框架,它提供了一种类似于Hibernate的编程思路,但相对于Hibernate来说,Mybatis更加灵活。与传统的JDBC相比,Mybatis可以帮助开发者更好地管理数据库连接和SQL语句,并且提供了一套解决对象持久化问题的解决方案。 在Mybatis中,可以使用XML文件或者注解来配置SQL语句和映射关系。XML文件中可以定义各种各样的SQL语句,包括增删改查等操作,同时可以使用占位符来动态地构建SQL语句。通过在Java代码中调用Mybatis的API,可以方便地执行SQL语句,查询数据库并获取结果。 Mybatis还提供了一套对象关系映射(ORM)机制,通过配置映射文件,将数据库表的数据Java对象进行映射。开发者可以通过在映射文件中定义SQL语句和结果映射规则来实现数据库Java对象之间的转换。这种映射关系可以提供对象的CRUD操作,并且可以通过配置实现对象关联查询和延迟加载等功能。 Mybatis的优点是轻量级、灵活性高、易于学习和使用。它不会对SQL语句进行封装,可以使用原生的SQL语句,方便开发者优化和调试。另外,Mybatis还支持插件的扩展机制,可以通过插件来增加一些自定义的功能,满足不同项目的需求。 总之,Mybatis是一个简、灵活且功能强大的持久层框架,可以有效地解决对象和数据库之间的映射关系问题,提高开发效率和代码质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值