MyBatis是什么?
MyBatis是dao层(持久层)框架,它支持自定义SQL、存储过程以及高级映射。
MyBatis 免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的XML或注解来配置和映射原始类型、接口和Java POJo (Plain old java Objects,普通老式Java对象)为数据库中的记录。
MyBatis流行的主要原因在于它的简单性和易使用性。在Java应用程序中,数据持久化层涉及到的工作有:
- 将从数据库查询到的数据生成所需要的Java对象
- 将Java对象中的数据通SQL持久化到数据库中
MyBatis通过抽象底层的JDBC代码,自动化封装SQL结果集产生Java对象、Java对象的数据持久化数据库中的过程使得对SQL的使用变得容易
MyBatis的特点
- 消除了大量的JDBC冗余代码
- 能很好地与传统数据库协同工作
- 提供了与Spring框架的集成支持
- 提供了与第三方缓存类库的集成支持
- 引入了更好的性能
Mybatis的执行原理
-
读取MyBatis 配置文件mybatis-config.xml,加载数据源、事务等
InputStream in= Resources.getResourceAsStream("mybatis-config.xml");
-
加载映射文件mapper.xml
<mappers> <!--resource: sql映射文件的路径 --> <!--一次性加载某个包下所有sql映射文件 要求: sql映射文件与接口必须位于同一个包下 --> <package name="com.fs.shop.mapper"/> </mappers>
-
定义SQL语句,在上一步的文件中加载。
-
创建会话工厂。(SqlSessionFactory)
private static SqlSessionFactory sqlSessionFactory; sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
-
创建会话(SqlSession)
sqlSession = sqlSessionFactory.openSession();
-
通过Executor 操作数据库
-
输入参数和输出结果
mybatis应用程序通过SqlSessionFactoryBuilder从mybatis-config.xml配置文件中构建出SqlSessionFactory,然后,SqlSessionFactory的实例直接开启一个SqlSession,再通过SqlSession实例获得Mapper对象并运行Mapper映射的SQL语句,完成对数据库的CRUD和事务提交,之后关闭SqlSession。
public static void main(String[] args) throws IOException {
// 加载mybatis配置文件
Reader reader = Resources.getResourceAsReader("config/configuration.xml");
// InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
//创建数据工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(reader);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
// 获取mapper接口对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 查询
User user = mapper.selectByPrimaryKey("1");
//释放会话
sqlSession.clearCache();
sqlSession.close();
}
初始化
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSessionFactory build方法里的XMLConfigBuilder是专门解析mybatis的配置文件的类,parser.parse()的返回值是Configuration对象,Configuration对象的结构和xml配置文件的对象几乎相同。
xml中的配置标签有哪些:
properties(属性),settings(设置),typeAliases(类型别名),typeHandlers(类型处理器),objectFactory(对象工厂),mappers(映射器)等
读取了xml文件各个标签内容并封装到Configuration中的属性中。
解析xml是对把xml文件中的标签内容复制到Configuration中的属性中
SqlSession sqlSession = factory.openSession();
MappedStatement Mybatis内部存储缓存
MappedStatement与Mapper配置文件中的一个select/update/insert/delete节点相对应。
mapper中配置的<select></select>等标签都被封装到了此对象中,然后存储在Configuration对象的mappedStatements属性中,mappedStatements 是一个HashMap,key为hashCode+sqlId+Sql语句 (全限定类名 + 方法名),value为从查询出来映射生成的java对象(MappedStatement对象)。
Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection")
进入 executor.query()
为本次查询创建缓存的Key,进入query的重载方法中,如果 A进程在对数据库操作的时候 B进程将sqlSession关闭了,会报throw new ExecutorException("Executor was closed.");
如果缓存中没有本次查找的值,那么从数据库中查询。
从数据库查询,调用查询方法 finally localCache.removeObject(key); 清空该key的value后将再查询结果放入缓存,
SimpleExecutor中实现父类的doQuery抽象方法,传入参数创建StatementHanlder对象来执行查询,创建jdbc中的statement对象,是原生jdbc的执行,StatementHandler进行处理 return handler.query(stmt, resultHandler); ResultHandler对象,用于对返回的结果进行处理
动态代理——通常的Mapper接口我们都没有实现的方法却可以使用
当判断解析到接口时,会创建此接口对应的MapperProxyFactory对象,存入HashMap中, key = 接口的字节码对象,value = 此接口对应的MapperProxyFactory对象。
MyBatis初始化时对接口的处理:MapperRegistry是Configuration中的一个属性,它内部维护一个HashMap用于存放mapper接口的
工厂类
MapperProxyFactory,每个接口对应一个工厂类MapperMethod最终调用了执行的方法 .execute(sqlSession, args)
command.getType() 判断mapper中的方法类型是insert还是delete,最终调用的还是SqlSession中的方法
此段为边阅读别人写的博客边复制的 (主要用于能够让自己读得下去。。)
原文链接:http://t.csdn.cn/Yl3Hv
掌握MyBatis的工作原理,要结合JDBC来理解MyBatis的工作原理往往才能更透彻。我们知道,JDBC有四个核心对象:
(1)DriverManager,用于注册数据库连接
(2)Connection,与数据库连接对象
(3)Statement/PrepareStatement,操作数据库SQL语句的对象
(4)ResultSet,结果集或一张虚拟表而MyBatis也有四大核心对象:
(1)SqlSession对象,该对象中包含了执行SQL语句的所有方法【1】。类似于JDBC里面的Connection 【2】。
(2)Executor接口,它将根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。类似于JDBC里面的Statement/PrepareStatement。
(3)MappedStatement对象,该对象是对映射SQL的封装,用于存储要映射的SQL语句的id、参数等信息。
(4)ResultHandler对象,用于对返回的结果进行处理,最终得到自己想要的数据格式或类型。可以自定义返回类型。原文链接:http://t.csdn.cn/KlzWU
- 通过Executor 操作数据库
SqlSession: 是一个接口
SqlSession是MyBatis中用于和数据库交互的
顶层类
,通常将它与ThreadLocal绑定,一个会话使用一个SqlSession,并且在使用完毕后需要close。使用的实现类: DefaultSqlSession
Executor接口的实现类:
BatchExecutor(重用语句并执行批量更新)
SimpleExecutor(普通的执行器,默认)
执行sql语句的属性: select
调用CachingExecutor的query()方法, CachingExecutor( 二级缓存) 二级缓存名: transactionalCaches HashMap
调用BaseExecutor的query()方法 BaseExcutor(一级缓存) 一级缓存: localCache HashMap
调用SimpleExecutor的doQuery()方法: 从数据库查询
执行selectById selectOne()也是调用selectList() 三目运算
list.isEmpt() || list ==null ? null : list.get(0)
找cache缓存 二级再到一级
BaseExecutor是SimpleExecutor的父类 子类没有的方法 使用的是继承父类的方法
一级缓存没有 才去数据库查询
父类没的方法 是执行子类重写的方法