Mybatis是如何工作的(一)
本文目标:
- 使用纯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加载配置的过程。内容相对粗浅,深入分析在下文。
相关推荐
xiuyangsong 2020-11-16
Nishinoshou 2020-11-09
jimgreatly 2020-09-01
dongxurr 2020-08-18
Dullonjiang 2020-08-15
Dullonjiang 2020-08-11
Dullonjiang 2020-08-09
dongxurr 2020-08-08
yunzhonmghe 2020-08-07
jimgreatly 2020-08-03
Dullonjiang 2020-07-30
jimgreatly 2020-07-27
liqiancao 2020-07-26
xiuyangsong 2020-07-26
dongxurr 2020-07-26
mcvsyy 2020-07-26
helloxusir 2020-07-25
牧场SZShepherd 2020-07-20