zoukankan      html  css  js  c++  java
  • 【mybatis】从一个错误,看mybatis中的#和$的区别

    事情的发展是这样的:

      因为一个需求,需要在java中拼接出一个完整的sql语句,然后将整条sql语句传递给mybatis执行。

    mapper.java是这样的:

    int insertMaster(WorksheetMasterSQLBean masterBean);

    这个对象是:

    public class WorksheetMasterSQLBean {
    
        private Long id;
    
        private String masterInsertSql;

    【就是用

    masterInsertSql 字段装了一下SQL,因为要在insert执行后返回自增ID的缘故,所以把SQL装在一个对象的属性中。主要就是想用一个bean的id取接收一下自增id.

    无所谓啦,往下看】【mybatis的insert返回自增id

    mapper.xml是这样的:

    【把sql放进insert标签中,执行】

      <insert id="insertMaster" parameterType="com.lqjava.daywork.api.beans.WorksheetMasterSQLBean" useGeneratedKeys="true" keyProperty="id">
            #{masterInsertSql}
        </insert>

    SQL语句是:

    【这就是在java中直接拼接好的sql语句】

    INSERT INTO   worksheet_data_14    (create_by,create_date,update_by,update_date,`input-number_0`)  VALUES (1,'2019-05-15 12:44:45',1,'2019-05-15 12:44:45','坦桑尼亚' )

    报错:

    【妈的,报错了】

    You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''INSERT INTO 

    原因:

    1.到了这里,就思考这个问题。

    我传入的参数,也就是String类型的sql语句,明明就是上面那个,为什么执行完了会报错。而且错误提示,就是在

    ''INSERT INTO

    这个地方?

    怀疑是不是在java中sql拼接的时候,自己多搞出来几个单引号在前面呀【或者空格之类的】

    2.仔细的debug了几次程序,发现,java中拼接出来的sql语句完全没有任何问题。

    既没有加单引号,又没有前后空格,也没有使用关键字这一说。

    那问题只能在将 sql送进mybatis之后,发生的问题了。

    3.这里就说到了mybatis的$#的区别

    首先:

      mybatis拼接sql时候,使用${参数} 和 #{参数} 都可以接受参数

    第二:

    例如:age = 1

    select * from user where age = #{age};
    select * from user where age = ${age};

    如果使用${参数},那就是将参数原原本本的进行字符串的替换,不会做任何过多的处理。

    看一下${}对上面的预编译的结果为

    select * from user where age = 1;

    如果使用#{参数},则会在预编译阶段生成占位符?,实际值的替换是在DBMS中进行的。

    看一下#{}对上面的预编译的结果为

    select * from user where age = ?;

    4.那看到了$和#的区别,为什么两个都可以在mybatis中使用?各自的优势何在

      1》#{},预编译生成占位符?,实际的参数值替换在DBMS中,根据参数类型,是否添加''单引号

        第一个优势:

          省时省力。那预编译的语句,会被缓存下来,下次相同的语句执行,不用编译,直接就可以拿到数据库操作,直接在数据库中进行参数替换即可。省时省力。

        第二个优势:

          防止SQL注入。如果像我上面的使用情况,我给占位符的地方传入的并不是一个值,而是一个;delete的删除语句,那直接传入数据库中,有了占位符替换的过程,会自动给string类型的加上''单引号在前后,这样就出现了上面我的错误。执行不了。

      2》${},直接进行字符串的替换

        那按上面那么说,${}就完全没有优势可言了么?

        不是的,就像上面的错误一样,这个时候就需要${}出马,才能直接将完整的sql语句替换。不会添加任何的''在前后。

        所以,像是如果mybatis中写了sql,但是表名是动态的,则需要${}。因为表名是不需要加''在前后的。

    5.对于mybatis中#和$的总结

      #{}是占位符号

      ${}是sql拼接符号

    解决方案:

    替换mapper.xml中的#为$,即可解决问题:

      <insert id="insertMaster" parameterType="com.lqjava.daywork.api.beans.WorksheetMasterSQLBean" useGeneratedKeys="true" keyProperty="id">
            ${masterInsertSql}
        </insert>
  • 相关阅读:
    发现程序bug思路
    streambase log(log4j和logback)
    streambase service 变为 window service启动
    机器学习-chapter1机器学习的生态系统
    eoe推荐的优秀博客
    Android Service 服务(一)—— Service .
    android startActivityForResult(Intent intent, int requestCode) 整理与总结! .
    Android Intent详解
    隐式Intent实例
    Android中的距离单位
  • 原文地址:https://www.cnblogs.com/sxdcgaq8080/p/10869144.html
Copyright © 2011-2022 走看看