一、介绍一下MyBatis
MyBatis 是一款优秀的持久层框架(ORM对象映射关系框架)
- 支持自定义 SQL、存储过程以及高级映射
- 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作
- 通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录
1.1.持久化:数据持久化
- 持久化就是将程序的数据在持久状态和瞬时状态转化的过程
- 内存:断电即失
- 数据库(jdbc):io文件持久化
为什么要持久化?
- 有一些对象不能让他丢掉
- 内存太贵了
1.2.持久层
Dao层、Service层、Controller层
- 完成持久化工作的代码块
- 层界限十分明显
1.4.为什么需要Mybatis?
- 方便
- 传统的JDBC代码太复杂了。
- 优点:可以在 XML 或注解中直接编写 SQL 语句,比较灵活,方便对 SQL 的优化与调整
- XML 中提供了动态 SQL 的标签,方便根据条件拼接 SQL
- 提供了 XML、注解与 Java 对象的映射机制(注解实现原理)
二、#{} 和 ${}的区别
- MyBatis 在处理 #{} 时,会将 SQL 中的 #{} 替换为 ?,预编译 SQL,通过 PreparedStatement 的setXxxx 的方法进行参数赋值。使用 #{} 可以有效地防止 SQL 注入。
#传入的参数在SQL中显示为字符串,#方式能够很大程度防止sql注入;$ 传入的参数在SqL中直接显示为传入的值,$方式无法防止Sql注入。
下面我们来看一下一种简单的注入,如果我们在表单中username的输入框中输入’ or 1=1-- ,password的表单中随便输入一些东西,假如这里输入123.此时我们所要执行的sql语句就变成了select id from users where username = ‘’ or 1=1-- and password = ‘123’,我们来看一下这个sql,因为1=1是true,后面 and password = '123’被注释掉了。所以这里完全跳过了sql验证。
三、MyBatis 中如何配置连接中断或执行超时?
Mybatis 的 XML 配置中,在 节点中添加子节点 ,name=defaultStatementTimeout,设置等待数据库响应的超时时间。
<settings>
<!-- 设置超时时间,它决定数据库驱动等待数据库响应的秒数 -->
<setting name="defaultStatementTimeout" value="25"/>
</settings>
四、Mybatis的一级缓存和二级缓存缓存及配置
一级缓存
SqlSession级别,也叫本地缓存,默认开启,只要在同一个SqlSession中,执行相同的查询语句,并且查的是同一个mapper.xml文件,那么会走一级缓存,SqlSession会话关闭的话,一级缓存就失效了。
上面的例子中,由于查询的都是id为1的用户,执行的sql语句也是一模一样的,并且是在同一个SqlSession中执行的,那么会走缓存。
上面的例子中,第二次查询id为1的用户是不走缓存的,因为增删改操作都会导致缓存失效,即使改的数据跟我们查的数据无关
一级缓存失效的情况:
- 查询不同的东西(sql语句必须一模一样才会走缓存)
- 增删改操作
- 查询不同的Mapper.xml
- 手动清理缓存(sqlsession.clearCache())
- SqlSession会话连接关闭
二级缓存
由于一级缓存作用域太低了,所以诞生了二级缓存,二级缓存是基于namespace级别的缓存,也就是一个命名空间,或者叫一个mapper.xml文件,对应一个二级缓存;开启二级缓存只需要在对应的mapper.xml文件声明一个 标签
上面这个例子应该是不走缓存的,虽然我们开启了二级缓存,但是由于二级缓存的工作机制是:SqlSession关闭时,一级缓存失效,才会将一级缓存中的东西放到二级缓存中,上面的例子由于sqlSession2执行查询的时候,sqlSession还未关闭,所以二级缓存中没有对应的缓存信息
如果是这个执行顺序的话,那么就会走缓存了
二级缓存小结: 只要开启了二级缓存,在同一个Mapper.xml文件下就能生效;所有的数据都会先放在一级缓存中,只有当会话提交,或者会话关闭的时候,才会提交到二级缓存中。
附:二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession去操作数据库得到数据会存在二级缓存区域,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。
二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。
Mybatis默认没有开启二级缓存需要在setting全局参数中配置开启二级缓存。
如果缓存中有数据就不用从数据库中获取,大大提高系统性能。
开启二级缓存
缓存的执行顺序
二级缓存的缺陷:此处
对于Sqlession此文链接:SqlSession原理
mybatis操作的时候跟数据库的每一次连接,都需要创建一个会话,我们用openSession()方法来创建。这个会话里面需要包含一个Executor用来执行 SQL
一切Mybatis配置都是为了创建SqlSession进行SQL查询;
五、MyBatis 如何批量插入?
方式一、打开批量插入的 SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
for (int i = 36; i <= 45; i++) {
userMapper.insertUser(new User(i, "ConstXiong" + i));
}
sqlSession.commit();
sqlSession.close();
方式二、拼接批量插入的 insert SQL
//Java 代码
List<User> userList = new ArrayList<>();
for (int i = 46; i <= 55; i++) {
userList.add(new User(i,"ConstXiong" + i));
}
userMapper.insertUserBatch(userList);
<!--Mapper xml 中配置-->
<insert id="insertUserBatch" parameterType="java.util.List">
insert into user values
<foreach collection="list" item="item" separator =",">
(#{
item.id}, #{
item.name})
</foreach>
</insert>
六、Mybatis的xml文件中,sql语句可以使用直接使用大于号小于号吗?应该用什么符号代替?
小于号 < 用 <
大于号 > 用 >
和 & 用 &
单引号 ’ 用 ’
双引号 " 用 "