zoukankan      html  css  js  c++  java
  • MyBatis 问题(持续更新)

    1.mybatis 比较符的写法

    第一种写法(1):
    原符号     <   <=       >     >=       &       '           "
    替换符号 &lt;  &lt;=  &gt;  &gt;=  &amp; &apos; &quot;
    例如:sql如下:
    create_date_time &gt;= #{startTime} and create_date_time &lt;= #{endTime}
    
    第二种写法(2):
    大于等于
    <![CDATA[ >= ]]>
    小于等于
    <![CDATA[ <= ]]>
    例如:sql如下:
    create_date_time <![CDATA[ >= ]]> #{startTime} and create_date_time <![CDATA[ <= ]]> #{endTime}

     2.mybatis中的#和$的区别

    动态 sql 是 mybatis 的主要特性之一,在mybatis中我们可以把参数传到xml文件,由mybatis对sql及其语法进行解析,mybatis支持使用${}和#{}。可能有些人没有留意到,认为${}和#{}的作用一样,其实他们的功能相似,但还是有区别的。

    对比

    1、使用${}方式传入的参数,mybatis不会对它进行特殊处理,而使用#{}传进来的参数,mybatis默认会将其当成字符串。可能在赋值给如id=#{id}和id=${id}看不出多大区别,但是作为表名或字段参数时可以明显看出,可以看看下面的例子:

    假设传入的参数为表名test

    select * from #{table};  
    #解析后是:select * from "test"; 
    select * from ${table};  
    #解析后是:select * from test; 

    很明显,前者多了字符串的引号,会失败,后者正常查询会成功;

    所以对于传入分组(order)字段或者排序字段(order),应使用${},避免出现order by "id" 等情况。

    2、#和$在预编译处理中是不一样的。#类似jdbc中的PreparedStatement,对于传入的参数,在预处理阶段会使用?代替,比如:

    select * from student where id = ?;  
    #待真正查询的时候即在数据库管理系统中(DBMS)才会代入参数。
    #而${}则是简单的替换,如下:
    select * from student where id = 2;  
    select * from tbl_employee where id=${id} and last_name=#{lastName}
    ​
    #Preparing: select * from tbl_employee where id=2 and last_name=?
    区别:

    #{}:是以预编译的形式,将参数设置到sql语句中;PreparedStatement;防止sql注入

    ${}:取出的值直接拼装在sql语句中;会有安全问题;

    大多情况下,我们去参数的值都应该去使用#{};

    原生jdbc不支持占位符的地方我们就可以使用${}进行取值

    比如分表、排序。。。;按照年份分表拆分

    select * from ${year}_salary where xxx;
    
    select * from tbl_employee order by ${f_name} ${order}

    总结

    1、能使用#{}的地方应尽量使用#{}

    2、像PreparedStatement ,#{}可以有效防止sql注入,${}则可能导致sql注入成功。

    所谓sql注入,就是指把用户输入的数据拼接到sql语句后面作为sql语句的一部分执行,例如:

    select * from user where name=' "+name+" ' and password=' "+password+" ' or  'abc' = 'abc';
    #那么只要用户输入用户名admin和密码123456,那么拼接出来的语句就为
    select * from user where name=' admin ' and password='123456' or 'abc'= 'abc';  
    #这样只要user表有数据,就会返回结果,达到sql注入的目的。同样,用户输入用户名a'则 and password=' "+password+" '就会被注释掉,也达到注入sql的目的。
    ​

    附:

    这里顺带提下防止sql注入的几种方式(可能不止这几种):

    (1)、jdbc使用 PreparedStatement代替Statement, PreparedStatement 不仅提高了代码的可读性和可维护性.而且也提高了安全性,有效防止sql注入;

    (2)、在程序代码中使用正则表达式过滤参数。使用正则表达式过滤可能造成注入的符号,如' --等

    (3)、在页面输入参数时也进行字符串检测和提交时进行参数检查,同样可以使用正则表达式,不允许特殊符号出现。

    resultType:返回值类型

    别名或者全类名,如果返回的是集合,定义集合中元素的类型(而不是集合本身)。

    resultMap:

    外部resultMap的命名引用,resultType与resultMap不能同时使用

     

    3.Mybatis缓存:(一级缓存和二级缓存)

    1.默认情况下,只有一级缓存(sqlSession级别的缓存,也成为本地缓存)开启

    2.二级缓存需要手动开启和配置,他是基于nameSpace级别的缓存

    3,.为了提高扩展性,mybatis定义了缓存接口Cache,我们可以通过实现Cache接口来自定义二级缓存

    一级缓存(local cache):

    也即本地缓存,作用域默认为sqlSession.当Session flush 或者close后,该session中的所有Cache将清空

    本地缓存不能被关闭,但可以调用clearCache()来清空本地缓存,或者改变缓存的作用域

    mybatis3.1后可以在mybatis.xml配置本地缓存的作用域

    一级缓存失效的情况

    1.不同的sqlsession对应不同的一级缓存

    2.同一个sqlsession但是查询条件不同

    3.同一个sqlsession 两次查询期间执行了任何一次增删改的操作

    4.同一个sqlsession 两次查询期间手动清空了缓存

    二级缓存:

    二级缓存,全局作用域缓存

    二级缓存默认不开启,需要手动配置

    mybatis提供二级缓存的接口一级实现,缓存实现要求POJO实现serializable接口

    二级缓存在sqlsession关闭或者提交后才会生效

    注意:当在一个作用域(一级缓存session或者二级缓存namespace)中进行了C/U/D操作后,默认该作用域下所有的select中的缓存将被clear

    4.开启mybatis 执行sql时,参数打印

    logging.level.com.xxx.xxx.payapply.mapper=DEBUG
  • 相关阅读:
    let 和 const 命令
    python连接oracle
    Python中小整数对象池和大整数对象池
    前端内容流程导图
    bootstrap插件的一些常用属性介绍
    bootstrap的引入和使用
    Linux 重定向
    Mongodb 备份 数据导出导入
    Mongodb 副本集
    Redis 模糊查询删除操作
  • 原文地址:https://www.cnblogs.com/weixiaotao/p/10422021.html
Copyright © 2011-2022 走看看