本文目标:使用纯Mybatis框架获取数据;理清Mybatis的工作过程。创建项目并运行首先创建maven项目,过程不再赘述。依赖如下:<dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.46</version> </dependency> </dependencies>下面准备一张表:CREATE TABLE clips
( id
int(11) NOT NULL AUTO_INCREMENT COMMENT ‘主键’, content
varchar(256) NOT NULL DEFAULT ’’ COMMENT ‘内容’, deleted
tinyint(1) NOT NULL DEFAULT ‘0’ COMMENT ‘删除标识:0正常,1删除’, create_time
datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ‘创建时间’, update_time
datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ‘更新时间’, PRIMARY KEY (id
)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=‘clips’;添加一条数据:对应的实体类:public class ClipsEntity { private Integer id; private String content; private Integer deleted; private LocalDateTime createTime; private LocalDateTime updateTime; // 省略getter和setter}DAO:public interface ClipsDAO { ClipsEntity selectById(@Param(“id”) Integer id);}mapper文件:<?xml version=“1.0” encoding=“UTF-8” ?><!DOCTYPE mapper PUBLIC “-//mybatis.org//DTD Mapper 3.0//EN” “http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace=“com.chunrun.dao.ClipsDAO”> <select id=“selectById” resultType=“com.chunrun.entity.ClipsEntity”> select * from clips where id = #{id} </select></mapper>Mybatis配置文件:<?xml version=“1.0” encoding=“UTF-8” ?><!DOCTYPE configuration PUBLIC “-//mybatis.org//DTD Config 3.0//EN” “http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration> <settings> <!–使用jdbc的getGeneratekeys获取自增主键值–> <setting name=“useGeneratedKeys” value=“true”/> <!–使用列别名替换别名 默认true–> <setting name=“useColumnLabel” value=“true”/> <!–开启驼峰命名转换Table:create_time到 Entity(createTime)–> <setting name=“mapUnderscoreToCamelCase” value=“true”/> <!– 打印查询语句 –> <setting name=“logImpl” value=“org.apache.ibatis.logging.stdout.StdOutImpl” /> </settings> <typeAliases> <typeAlias alias=“ClipsEntity” type=“com.chunrun.entity.ClipsEntity”/> </typeAliases> <environments default=“development”> <environment id=“development”> <transactionManager type=“JDBC”/> <dataSource type=“POOLED”> <property name=“driver” value=“com.mysql.jdbc.Driver”/> <property name=“url” value=“jdbc:mysql://localhost:3306/bizu”/> <property name=“username” value=“chunrun”/> <property name=“password” value=“chunrun1s”/> </dataSource> </environment> </environments> <mappers> <mapper resource=“mapper/ClipsDAO.xml”/> </mappers></configuration>下面写个测试:public class Main { public static void main(String[] args) { String resource = “mybatis-config.xml”; try { InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = factory.openSession(); ClipsDAO clipsDAO = session.getMapper(ClipsDAO.class); ClipsEntity clipsEntity = clipsDAO.selectById(1); System.out.println(clipsEntity); } catch (Exception e) { System.out.println(e); } }}运行结果:运行成功。那么,在这个过程中,程序具体做了什么事呢?一步一步来看。首先,我们用配置文件生成了一个InputStream;然后用InputStream生成了生成SqlSessionFactory;然后获取Session;获取对应的mapper,执行SQL获取结果。Mybatis做的事情主要有三步:从配置文件中生成SqlSessionFactory;从SqlSessionFactory中获取session;获取对应的mapper,执行SQL。下面逐步看源码。加载mybatis配置,生成SqlSessionFactory // 首先调用的是这个方法: public SqlSessionFactory build(InputStream inputStream) { return build(inputStream, null, null); } // 然后是这个: public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { try { // 根据参数获取一个XMLConfigBuilder,这部分是重点 XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException(“Error building SqlSession.”, e); } finally { ErrorContext.instance().reset(); try { inputStream.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } } } // 返回的build方法如下,可以看出实现是DefaultSqlSessionFactory public SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); }注释部分已经很清楚了,下面重点看下XMLConfigBuilder,Mybatis通过这个类来解析mybatis对应的配置。 // 解析configuration节点下面的子节点,并返回最终的配置。 public Configuration parse() { if (parsed) { throw new BuilderException(“Each XMLConfigBuilder can only be used once.”); } parsed = true; parseConfiguration(parser.evalNode("/configuration”)); return configuration; } private void parseConfiguration(XNode root) { try { //issue #117 read properties first // 加载properties节点下的属性, propertiesElement(root.evalNode(“properties”)); // 加载settings节点下的属性 Properties settings = settingsAsProperties(root.evalNode(“settings”)); loadCustomVfs(settings); // 加载别名配置 typeAliasesElement(root.evalNode(“typeAliases”)); // 加载插件配置 pluginElement(root.evalNode(“plugins”)); // 加载objectFactory配置 objectFactoryElement(root.evalNode(“objectFactory”)); // 加载objectWrapperFactory配置 objectWrapperFactoryElement(root.evalNode(“objectWrapperFactory”)); // 加载reflectorFactory配置 reflectorFactoryElement(root.evalNode(“reflectorFactory”)); settingsElement(settings); // read it after objectFactory and objectWrapperFactory issue #631 // 加载environment配置,这里会配置事务管理器 environmentsElement(root.evalNode(“environments”)); // 加载databaseIdProvider配置 databaseIdProviderElement(root.evalNode(“databaseIdProvider”)); // 加载typeHandler是配置,自定义的typeHandler会在这注册 typeHandlerElement(root.evalNode(“typeHandlers”)); // 加载mapper配置 mapperElement(root.evalNode(“mappers”)); } catch (Exception e) { throw new BuilderException(“Error parsing SQL Mapper Configuration. Cause: " + e, e); } } 至此,mybatis配置加载完成。小结本文主要介绍了如何使用纯Mybatis操作数据库,然后介绍了Mybatis加载配置的过程。内容相对粗浅,深入分析在下文。