MyBatis核心流程以及工作原理
MyBatis核心对象根据以下这四大核心对象我们就能理清MyBatis的工作原理。SqlSession对象该对象中包含了执行SQL语句的所有方法。类似于JDBC里面的Connection。Executor接口它将根据SqlSession传递的参数动态地生成需要执行的SQL语句同时负责查询缓存的维护。类似于JDBC里面的Statement/PrepareStatement。MappedStatement对象该对象是对映射SQL的封装用于存储要映射的SQL语句的id、参数等信息。ResultHandler对象用于对返回的结果进行处理最终得到自己想要的数据格式或类型。可以自定义返回类型。MyBatis工作原理上面中流程就是MyBatis内部核心流程每一步流程的详细说明如下文所述读取MyBatis的配置文件。mybatis-config.xml为MyBatis的全局配置文件用于配置数据库连接信息。加载映射文件。映射文件即SQL映射文件该文件中配置了操作数据库的SQL语句需要在MyBatis配置文件mybatis-config.xml中加载。mybatis-config.xml 文件可以加载多个映射文件每个文件对应数据库中的一张表。构造会话工厂。通过MyBatis的环境配置信息构建会话工厂SqlSessionFactory。创建会话对象。由会话工厂创建SqlSession对象该对象中包含了执行SQL语句的所有方法。Executor执行器。MyBatis底层定义了一个Executor接口来操作数据库它将根据SqlSession传递的参数动态地生成需要执行的SQL语句同时负责查询缓存的维护。MappedStatement对象。在Executor接口的执行方法中有一个MappedStatement类型的参数该参数是对映射信息的封装用于存储要映射的SQL语句的id、参数等信息。输入参数映射。输入参数类型可以是Map、List等集合类型也可以是基本数据类型和POJO类型。输入参数映射过程类似于JDBC对preparedStatement对象设置参数的过程。输出结果映射。输出结果类型可以是Map、List等集合类型也可以是基本数据类型和POJO类型。输出结果映射过程类似于JDBC对结果集的解析过程。注意在MyBatis中SqlSession对象包含了执行SQL语句的所有方法。但是它是委托Executor执行的。从某种意义上来看MyBatis里面的SqlSession类似于JDBC中的Connection它们都是委托给其它类去执行。MyBatis整合Log4j框架Mybatis 通过使用内置的日志工厂提供日志功能。内置日志工厂将会把日志工作委托给下面的实现之一SLF4JApache Commons LoggingLog4j 2Log4jJDK loggingsqlSession.close();MyBatis 内置日志工厂会基于运行时检测信息选择日志委托实现。它会按上面罗列的顺序使用第一个查找到的实现。当没有找到这些实现时将会禁用日志功能。通过在 MyBatis 配置文件 mybatis-config.xml 里面添加一项 setting来选择其它日志实现。这里以log4j为例。configuration settings ... setting namelogImpl valueLOG4J/ ... /settings /configuration配置log4j假设你需要记录这个映射器的日志package com.xyr.dao; import com.xyr.domain.User; import org.apache.ibatis.annotations.Select; public interface UserMapper { Select(select * from user where id #{id}) User selectUserById(Integer id); }在应用的类路径中创建一个名为 log4j.properties 的文件文件的具体内容如下# 全局日志配置 log4j.rootLoggerERROR, stdout # MyBatis 日志配置 log4j.logger.com.xyr.dao.UserMapperTRACE # 控制台输出 log4j.appender.stdoutorg.apache.log4j.ConsoleAppender log4j.appender.stdout.layoutorg.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern%5p [%t] - %m%n实现结果如下上述配置将使 Log4J 详细打印 com.xyr.dao.UserMapper 的日志对于应用的其它部分只打印错误信息。为了实现更细粒度的日志输出你也可以只打印特定语句的日志。以下配置将只打印语句selectUserById 的日志log4j.logger.com.xyr.dao.UserMapper.selectUserByIdTRACE为了实现更粗粒度的日志输出你也可以打印所有mapper的日志。以下配置将只打印所有mapper 的日志log4j.logger.com.xyr.daoTRACE在实际开发中往往查出来的数据经常可能会有成百上千条如果希望不显示查询出来的数据让控制台更加清晰可以设置日志的显示级别设置为DEBUG级别可以不显示查询结果如下所示log4j.logger.com.xyr.dao.UserMapperDEBUG注意为映射器和 XML 文件打开日志功能的语句毫无差别。MyBatis基于XML配置实现CRUD引入自定义代码工具类MyBatisUtilspackage com.xyr.utils; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException; import java.io.InputStream; /** * Title 针对MyBatis框架的一些固定步骤进行二次封装 * Author zhk * Description: */ public class MyBatisUtils { private static SqlSessionFactory factory; private MyBatisUtils() {} static { try { InputStream is Resources.getResourceAsStream(mybatisconfig.xml); factory new SqlSessionFactoryBuilder().build(is); } catch (Exception e) { e.printStackTrace(); } } public static SqlSession getSqlSession() { return factory.openSession(); } public static void close(SqlSession session) { if (Objects.nonNull(session)) { session.close(); } } }SqlSession默认不自动提交事务可使用sqlSessionFactory.openSession(true); 来自动提交事务。添加操作添加用户记录UserMapper类代码如下所示public interface UserMapper { int insertUser(User u); }UserMapper.xml配置如下所示insert idinsertUser parameterTypecom.xyr.domain.User insert into user(name, password, age) values(#{name}, #{password}, #{age}) /insert测试代码如下所示package com.xyr.dao; import com.xyr.domain.User; import com.xyr.utils.MyBatisUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Before; import org.junit.Test; /** * Title * Author Xyr * Description: */ public class UserMapperTest { private SqlSession sqlSession; private UserMapper mapper; Before public void init() { sqlSession MyBatisUtils.getSqlSession(); mapper sqlSession.getMapper(UserMapper.class); } After public void destroy() { MyBatisUtils.close(sqlSession); } Test public void testInsert() { User u new User(); u.setName(张三); u.setPassword(123456); u.setAge(18); mapper.insertUser(u); sqlSession.commit(); } }注意添加操作属于DML语句针对DML语句需要进行事务的提交所以需要手动调用sqlSession对象的commit方法进行显示提交。主键回填在增加操作中如果设置了主键id是自增的那么插入数据时id的值一般写null因为存入数据库时id都会自动1看似操作没毛病非常完美。但是在购物交易的添加模块这可不兴这样细想一下在上网买东西时用户付完钱之后一般都会返回一个订单编号其实这个订单编号在数据库中就是主键但是因为在插入数据时id的值写了null所以订单编号也为null也就是说返回不了订单编号的数据。方式一使用 useGeneratedKeys 属性insert idinsertUser parameterTypeUser useGeneratedKeystrue keyPropertyid insert into user(name, password, age) values(#{name}, #{password}, #{age}) /insert方式二使用 selectKey 标签insert idinsertUser parameterTypeUser selectKey keyPropertyid keyColumnid resultTypejava.lang.Integer orderAFTER select last_insert_id() /selectKey insert into user(name, password, age) values(#{name}, #{password}, #{age}) /insert如果id的值是字符串类型的uuid时数据库就不能够主键自动生成那么可以考虑使用方式二来实现insert idinsertUser2 parameterTypecom.xyr.domain.User2 selectKey resultTypejava.lang.String keyColumnid keyPropertyid orderBEFORE select uuid(); /selectKey insert into t_user(id, name, password, age) values(#{id}, #{name}, #{password}, #{age}) /insert详细请参考 Mybatis---主键回填 (*^▽^*)_数据库_Lynn Lu-DevPress官方社区 (csdn.net)删除操作通过id删除用户记录更新操作通过id更新用户记录测试代码如下Test public void testUpdate() { User u new User(); u.setId(11); u.setName(宋小宝); u.setPassword(666666); u.setAge(30); mapper.updateUserById(u); sqlSession.commit(); }查询操作通过id查询单个用户查询所有用户测试代码如下Test public void testSelectAllUsers() { mapper.selectAllUsers(); }

相关新闻