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

 

posted @ 2019-02-23 11:20  小白个人成长记  阅读(391)  评论(0编辑  收藏  举报