Mybatis作为一款优秀的ORM框架,除了支持对象与关系数据库之间映射外,还支持开发人员自由编写SQL语句。本文将以Mybatis执行原生SQL为中心,从锁、SQL语句的执行、Mybatis执行原理以及执行流程这四个方面进行详细阐述。
一、锁
在多个并发事务同时修改同一数据时,数据库需要通过一定的方法来维持事务的隔离性,防止数据异常。锁是维护数据库并发事务细粒度和隔离性的重要手段之一,为了保证数据的正确性和一致性,应尽量使用锁。Mybatis支持使用数据库提供的锁形式来进行并发控制。
Mybatis支持在Mapper.xml文件中通过select … for update
的方式实现悲观锁和乐观锁,对于需要锁定的数据,在SQL语句中要使用FOR UPDATE子句,如下例:
<select id="selectForUpdate" parameterType="java.lang.Integer"
resultType="com.example.demo.model.User">
select * from user where id = #{id} for update
</select>
这种方式适用于需要锁住一部分数据,使其不被其他事务修改的场景,和防止读脏数据的情况发生。
二、SQL语句的执行
Mybatis将SQL的执行过程分为解析阶段、绑定阶段、执行阶段、结果集处理阶段四个步骤。
1. 解析阶段
解析Mapper.xml文件中定义的SQL语句,将SQL语句分解成各个部分,如:语法关键字、表名、where子句等。
2. 绑定阶段
将SQL语句中的参数进行绑定,Mybatis在绑定时,会将参数值替换到SQL语句中对应的位置,从而构造出可执行的SQL语句。
3. 执行阶段
Mybatis通过JDBC连接数据库,并调用JDBC API执行SQL语句。在执行SQL语句前,Mybatis会进行表前缀和后缀的配置、分页查询、多表查询、存储过程调用等功能。
4. 结果集处理阶段
Mybatis会将JDBC返回的数据转换为Java对象,并通过映射文件或注解将数据封装到对象中,最后返回给上层调用者。
三、Mybatis执行原理
Mybatis执行原理是通过调用SqlSession对象的API来实现的。执行原生SQL一般分为以下几步:
1. 获取SqlSessionFactory对象
SqlSessionFactory是创建SqlSession实例的工厂类,Mybatis的启动过程中加载Mapper解析配置文件,生成SqlSession工厂实例。
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new
SqlSessionFactoryBuilder().build(inputStream);
2. 打开SqlSession
通过SqlSessionFactory打开一个数据连接,SqlSession就是进行数据库操作的关键对象。操作完后一定要记得关闭。
SqlSession sqlSession = sqlSessionFactory.openSession();
3. 执行查询
SqlSession有多个方法对应不同的查询方式。我们可以通过selectOne或selectList来执行查询,其中selectOne返回单个对象,selectList返回对象列表。
User user = sqlSession.selectOne("com.example.demo.UserMapper.selectById", 1);
List
userList = sqlSession.selectList("com.example.demo.UserMapper.selectAll");
4. 提交事务、关闭SqlSession
当数据库操作结束后,需要提交事务,也就是确认对数据库的修改。如果SqlSession未提交,则所做的修改不会被写入到数据库。最后一定要关闭SqlSession。
sqlSession.commit();
sqlSession.close();
四、Mybatis执行原理流程
Mybatis执行原理的整个流程如下图所示:
从图中可以看出,Mybatis执行原理的流程比较简单,可以轻松理解和掌握。
总结
本文从锁、SQL语句的执行、Mybatis执行原理以及执行流程这四个方面详细阐述了Mybatis执行原生SQL的相关知识。在实际的开发中,需要根据具体的情况选择获取SqlSessionFactory对象、打开SqlSession、执行查询以及提交事务等操作。同时,在SQL语句的编写中,也需要注意防止SQL注入攻击等问题,保证代码的安全性。