高端网站建设公司哪家更专业,wordpress 搜索 自定义,广州市网站网页制作公司,近期国内重大新闻说一下MyBatis执行流程#xff1f;
MyBatis是一款优秀的基于Java的持久层框架#xff0c;它内部封装了JDBC#xff0c;使开发者只需要关注SQL语句本身#xff0c;而不需要花费精力去处理加载驱动、创建连接等的过程#xff0c;MyBatis的执行流程如下#xff1a;
加载配…说一下MyBatis执行流程
MyBatis是一款优秀的基于Java的持久层框架它内部封装了JDBC使开发者只需要关注SQL语句本身而不需要花费精力去处理加载驱动、创建连接等的过程MyBatis的执行流程如下
加载配置文件MyBatis的执行流程从加载配置文件开始。通常MyBatis的配置文件是一个XML文件其中包含了了数据源配置SQL映射配置、连接池配置构架SqlSessionFactory在配置文件加载后MyBatis使用配置信息来构建SqlSessionFactory这是MyBatis的核心工厂类。SqlSessionFactory是线程安全的它用于创建SqlSession对象创建SqlSession应用程序通过SqlSessionFactory床渐渐SqlSession对象。SqlSession代表依次数据库会话它提供了执行SQL操作的方法。通常情况下每个线程都应该由自己的SqlSession对象执行SQL查询在SqlSession种开发人员可以执行SQL查询你这可以通过两种方式实现 使用注解加SQLMybatis提供了注解加执行SQL的实现方式MyBatis会为Mapper接口生成实现类的代理对象实际执行SQL查询使用XML映射文件开发人员可以在XML映射文件中定义SQL查询语句和映射关系。然后通过SqlSession执行这些SQL擦汗寻将结果有映射到Java对象上SQL解析和执行MyBatis会解析SQL查询执行查询操作并获取查询结果结果映射MyBatis使用配置的结果映射规则将查询结果映射到Java对象上。这包括将数据库列映射到Java对象的属性上并处理关联关系返回结果查询结果被返回给应用程序开发热恩于那可以对结果进行进一步处理、展示或之旧话关闭SqlSession完成数据库操作后关闭SqlSession释放资源
${}和#{}有什么区别什么情况下一定要使用${}
${}和#{}都是MyBatis种用来代替参数的特殊标识如下
但是二者的区别二还是很大的主要区别如下
含义不同${}是直接替换运行时已经替换成具体的执行SQL了而#{}是预处理运行时只设置了占位符?之后通过声明器statement来替换占位符使用场景不同普通参数使用#{}如果传递的是SQL命令如desc还是asc或者SQL关键字的时候需要使用${}但是使用之前一定要做好安全验证安全性不同使用${}存在安全性问题#{}不存在安全性问题
也就是说为了防止安全问题所以大部分场景都要使用 #{} 替换参数但是如果传递的是 SQL 关键字例如order by xxx asc/desc 时(传递 asc 后 desc)一定要使用 $因为它需要在执行时就被替换成关键字而不能使用占位符替代(占位符不用应用于 SQL 关键字否则会报错)。
在传递 SOL 关键字时一定要使用 ${}但使用前一定要进行过滤和安全检査以防止 SQL 注入。
什么是SQL注入如何防止SQL注入
SQL注入就是指应用程序对用户输入的数据的合法性没有判断或过滤不严攻击者可以在应用程序中事先定义好查询语句的结尾上添加额外的SQL语句在管理员不知情的情况下实现非法操作依次来实现欺骗数据库服务器执行非授权的热议操作从而进一步得到相应的数据信息 也就是说所谓的 SQL 注入指的是使用某个特殊的 SQL 语句利用 SQL 的执行特性绕过 SQL 的安全检查,查询到本不该查询到的结果
如以下代码
select iddoLogin resultTypecom.example.demo.model.Userselect *from userinfo where username${name} and password${pwd}
/select
sql注入以下代码 or 11如下图所示
从上述结果可以看出以上程序在应用程序不知情的情况下实现非法操作以此来实现欺骗数据库服务器执行非授权的敏感数据
如何防止SQL注入
预编译语句与参数化查询使用 PreparedStatement 可以有效防止 SQL 注入因为它允许你先定义 SQL 语句的结构然后将变量作为参数传入数据库驱动程序会自动处理这些参数的安全性确保它们不会干扰 SQL 语句的结构如下代码所示:
String sql SELECT * FROM users WHERE username ? AND password ?;
PreparedStatement pstmt connection.prepareStatement(sql);
pstmt.setString(1,userInputUsername);
pstmt.setstring(2,userInputPassword);
ResultSet rspstmt.executeQuery();
输入验证和过滤对用户输入的信息进行验证和过滤确保其符合预期的类型和格式
说一下MyBaits中的二级缓存
MyBatis二级缓存是用于提高MyBatis查询数据库的性能和减少访问数据库的机制。MyBatis的二级缓存总共由两个缓存机制
一级缓存SqlSession级别的MyBatis自带的缓存功能。并且无法关闭因此当有两个SqlSession访问相同的SQL时一级缓存也不会生效也需要查询两次数据库。在一个service调用两个相同的mapper方法的时候依然是查询两次因为他会创建那两个SqlSession进行查询为了提高查询性能二级缓存Mapper级别的只要是同一个Mapper无论是使用多少个SqlSession来操作数据都是共享的。也就是说一个sessionFactory下的多个session之间是共享缓存的它的作用范围更大生命周期更长可以减少数据库的查询次数提高系统性能。但是MyBatis二级缓存时默认关闭的需要手动开启
二级缓存默认是不开启的手动开启MyBatis步骤如下
在mapper.xml中添加cache/标签在需要缓存的标签上添加usrCachetrue新版本可以忽略为了兼顾老版本保留
完整示例如下
?xml version1.0 encodingUTF-8?
!DOCTYPE mapper PUBLIc -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.mybatis.demo.mapper.StudentMappercache/select idgetStudentCount resultTypeInteger usecachetrueselect count(*)from student/select
/mapper
编写单元测试代码
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; SpringBootTest
public class StudentMapperTest { Autowired private StudentMapper studentMapper; Test void testGetStudentCount() { int count studentMapper.getStudentCount(); System.out.println(查询结果: count); int count2 studentMapper.getStudentCount(); System.out.println(查询结果2: count2); }
}
运行结果
从以上结果可以看出两次查询虽然使用了不同的 SqlSession但第二次查询使用了缓存并未查询数据库
ORM项目中类属性名和数据库字段名不一致会导致什么问题它的解决方案有哪些
在ORM项目中如果类的属性名称和数据库字段名不一致会场导致插入、修改时设置的这个不一致字段为null查询的时候即使数据库有数据但是查询的结果也是为null。它的常见解决方法如下
更改程序中属性名或数据库的字段名使其一致使用结果映射使用resultMap映射对应的字段 !-- 在 XML 配置文件中定义 resultMap --
resultMap iduserResultMap typecom.example.User!-- 指定 id 字段映射 --id propertyid columnid/!-- 指定 username 字段映射 --result propertyusername columnusername/!-- 指定 email 字段映射 --result propertyemail columnemail/
/resultMap
//在SQL映射文件中可以使用这个resultMap来进行查询结果的映射
select idselectUser resultMapuserResultMapSELECT id, username, emailFROM userWHERE id #{id}
/select使用MyBatis Plus框架中的TableFild注解映射二者的字段如下图 如果是查询操作 可以使用as重命名字段名这样查询也就不会为null了
MyBatis中如何实现分页它有几种实现分页的方式
MyBatis中实现分页主要是一下两种实现方式
物理分页物理上是使用SQL擦哈寻语句在数据库引擎层面实现的如MySQL的LIMIT语法进行分页逻辑分页逻辑分页时在应用程序层面进行的分页通常是先查询出所有符合条件的数据然后在内存中对数据进行分页操作
物理分页
使用limit实现分页
物理分页是可以直接在XML中拼加SQL进行分页
select idgetUserListresultTypeUserselect *from userlimit #{limit} offset #{offset}
/select
使用PageHelper插件实现分页
实现代码如下
PageHelper.startPage(110);
//1 表示要查询的页码为第一页10 表示每页显示的记录数为 10 条
ListUserlistuserMapper.selectIf(1); PageHelper实现原理分析
PageHelper底层是使用MyBatis的拦截器Interceptor机制在MyBatis进行查询时拦截并对SQL语句进行动态修改添加limit等分页查询操作之后查询数据库、并对查询结果进行包装包装成分页对象如包含数据列表、总记录数、总页数等信息的分页对象最后再将这个分页对象返回给客户端
逻辑分页
MyBatis自带的RowBounds进行分页就是逻辑分页它的一次性查询很多数据然后在数据中在进行检索实现代码如下
RowBounds rowBounds new RowBounds(offset, limit);
ListUser users sqlSession.selectList(getUserList, null, rowBounds);其中 offset 为起始行偏移量limit 是每页数据量虽然设置了这两个值但在使用 RowBounds 时它会一次性查询多条数据然后再在内存中进行 offset 和 limit 的筛选最后在返回符合结果的数据
MyBaits二级缓存有几种淘汰策略如何设置缓存淘汰策略
LRU-最近最少使用移除最长时间不被使用的对象FIFO-先进先出按照对象进入缓存的顺序来移除对象SOFT-软引用基于垃圾回收器状态和软引用规则移除对象WEAK-弱引用更积极地基于垃圾收集器状态和弱引用规则移除对象
默认的缓存淘汰策略时LRU
可以通过eviction属性来设置淘汰策略如下
cache evictionFIFO/
MyBatisPlus如何实现分页功能它的底层是如何实现的
MyBatis-Plus 是 MyBatis 的增强工具在 MyBatis 的基础上提供了更多方便的功能包括分页功能。在 MyBatis-Plus 中实现分页功能非常简单主要使用 Page 类进行分页操作。
以下是使用 MyBatis-Plus 实现分页功能的基本步骤
在 Mapper 接口中定义查询方法并接收一个 Page 类型的参数用于分页
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;public interface UserMapper extends BaseMapperUser {PageUser selectUserPage(PageUser page);
}在 Mapper XML 文件中编写对应的 SQL 查询语句
select idselectUserPage resultTypecom.example.Userselect * from user
/select在 Service 层调用 Mapper 中定义的查询方法并传入一个 Page 对象作为参数
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;Service
public class UserServiceImpl implements UserService {Autowiredprivate UserMapper userMapper;Overridepublic PageUser selectUserPage(int pageNum, int pageSize) {PageUser page new Page(pageNum, pageSize);return userMapper.selectUserPage(page);}
}这样就完成了分页功能的实现。MyBatis-Plus会自动将查询结果封装到Page对象中其中包含了分页的相关信息比如当前页码、每页大小、总记录数等
MyBatis-Plus底层是通过拦截器实现分页的它会在执行SQL语句前进行拦截并根据传入的分页参数自动生成对应的分页SQL语句然后执行分页查询。最后将查询结果封装到Page对象中返回给调用方。这样开发人员不需要手动编写分页的SQL语句简化了开发流程
MyBatis中使用了哪些设计模式举例说明一下
工厂模式工厂模式是Java中最常见的设计模式之一。工厂模式就是它提供一个工厂当有客户需要调用的时候只调用这个工厂类就可以得到自己想要的结果从而无需关注某类的具体实现过程。工厂模式在MyBatis中典型的代表就是SqlSessionFactory。SqlSession是MyBatis中的重要而Java接口可以通过该接口来执行SQL语句获取映射器示例和管理事务而SqlSessionFactory正在用来产生SqlSession对象的所以它在MyBatis中是比较核心的接口建造者模式建造者模式就是将一个复杂对象的构建与它的表示分离使得的同样的构建过程可以创建不同的表示。也就是说建造者可以通过多个模块一步一步实现对象的构建相同的构建过程可以创建不同产品。建造者模式在MyBatis中典型代表就是SqlSessionFactoryBuilder。普通的对象都是通过new关键字直接创建的但是如果创建对象需要构造参数很多且不能保证每个参数都是正确的或者不能一次性得到构建所需的所有参数那么就需要将构建逻辑从对象本身抽离出来让对象只关注功能把构建交给构建类这样就可以简化对象的构建也可以达到分布构建对象的目的单例模式单例模式是Java中最简单的设计模式之一此模式保证某个类在运行期间只有一个实例对外提供服务而这类被称为单例类。单例模式在MyBatis中典型的代表就是ErrorContext。ErrorContext是线程级别的单例每一个线程有一个此对象的单例用于记录该现成的执行环境的错误信息代理模式代理模式是指给某个对象提供一个代理对象并由代理对象控制原对象的调用。代理模式在MyBatis中典型的代表就是MapperProxyFactory。MapperProxyFactory的newInstance方法就是生成一个具体的代理类来实现某个功能