#0 系列目录#java
MyBatis 是一个能够自定义SQL、存储过程和高级映射
的持久层框架。MyBatis 摒除了大部分的JDBC代码、手工设置参数和结果集重获
。MyBatis 只使用简单的XML 和注解来配置和映射基本数据类型、Map 接口和POJO 到数据库记录
。相对Hibernate和Apache OJB等“一站式”ORM解决方案而言,Mybatis 是一种“半自动化”的ORM实现
。mysql
ORM工具的基本思想,不管是用过的hibernate,mybatis,你均可以法相他们有一个共同点:sql
#1 Mybatis的功能架构## ##1.1 功能架构分为三层##数据库
API接口层:提供给外部使用的接口API
,开发人员经过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等
。它主要的目的是根据调用的请求完成一次数据库操做。基础支撑层:负责最基础的功能支撑
,包括链接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来做为最基础的组件。为上层的数据处理层提供最基础的支撑。而下面是MyBatis源码包对应的架构图:apache
##1.2 快速入门## 缓存
每个MyBatis的应用程序的入口是SqlSessionFactoryBuilder
,它的做用是经过XML配置文件建立Configuration对象(固然也能够在程序中自行建立),而后经过build方法建立SqlSessionFactory对象。没有必要每次访问Mybatis就建立一次SqlSessionFactoryBuilder,一般的作法是建立一个全局的对象就能够了
。示例程序以下:安全
private static SqlSessionFactoryBuilder sqlSessionFactoryBuilder; private static SqlSessionFactory sqlSessionFactory; private static void init() throws IOException { String resource = "mybatis-config.xml"; Reader reader = Resources.getResourceAsReader(resource); sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); sqlSessionFactory = sqlSessionFactoryBuilder.build(reader); }
SqlSessionFactory对象由SqlSessionFactoryBuilder建立
。它的主要功能是建立SqlSession对象,和SqlSessionFactoryBuilder对象同样,没有必要每次访问Mybatis就建立一次SqlSessionFactory,一般的作法是建立一个全局的对象就能够了
。SqlSessionFactory对象一个必要的属性是Configuration对象,它是保存Mybatis全局配置的一个配置对象,一般由SqlSessionFactoryBuilder从XML配置文件建立。这里给出一个简单的示例:session
<?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> <!-- 配置别名 --> <typeAliases> <typeAlias type="org.iMybatis.abc.dao.UserDao" alias="UserDao" /> <typeAlias type="org.iMybatis.abc.dto.UserDto" alias="UserDto" /> </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://127.0.0.1:3306/iMybatis?characterEncoding=GBK" /> <property name="username" value="iMybatis" /> <property name="password" value="iMybatis" /> </dataSource> </environment> </environments> <!-- 配置mappers --> <mappers> <mapper resource="org/iMybatis/abc/dao/UserDao.xml" /> </mappers> </configuration>
SqlSession对象的主要功能是完成一次数据库的访问和结果的映射,它相似于数据库的session概念,因为不是线程安全的,因此SqlSession对象的做用域需限制方法内。SqlSession的默认实现类是DefaultSqlSession
,它有两个必须配置的属性:Configuration和Executor。Configuration前文已经描述这里再也不多说。SqlSession对数据库的操做都是经过Executor来完成的。mybatis
SqlSession有一个重要的方法getMapper,顾名思义,这个方式是用来获取Mapper对象的。什么是Mapper对象?根据Mybatis的官方手册,应用程序除了要初始并启动Mybatis以外,还须要定义一些接口,接口里定义访问数据库的方法,存放接口的包路径下须要放置同名的XML配置文件
。SqlSession的getMapper方法是联系应用程序和Mybatis纽带,应用程序访问getMapper时,Mybatis会根据传入的接口类型和对应的XML配置文件生成一个代理对象,这个代理对象就叫Mapper对象
。应用程序得到Mapper对象后,就应该经过这个Mapper对象来访问Mybatis的SqlSession对象,这样就达到里插入到Mybatis流程的目的。架构
SqlSession session= sqlSessionFactory.openSession(); UserDao userDao = session.getMapper(UserDao.class); UserDto user = new UserDto(); user.setUsername("iMybatis"); List<UserDto> users = userDao.queryUsers(user);
public interface UserDao { public List<UserDto> queryUsers(UserDto user) throws Exception; }
<?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="org.iMybatis.abc.dao.UserDao"> <select id="queryUsers" parameterType="UserDto" resultType="UserDto" useCache="false"> <![CDATA[ select * from t_user t where t.username = #{username} ]]> </select> </mapper>
Executor对象在建立Configuration对象的时候建立,而且缓存在Configuration对象里。Executor对象的主要功能是调用StatementHandler访问数据库,并将查询结果存入缓存中(若是配置了缓存的话)
。
StatementHandler是真正访问数据库的地方,并调用ResultSetHandler处理查询结果。
处理查询结果。
#2 Mybatis环境搭建及简单实例# ##2.1 Maven依赖##
<dependencies> <!-- 添加junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!-- 添加log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.16</version> </dependency> <!-- 添加mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.6</version> </dependency> <!-- 添加mysql驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.12</version> </dependency> </dependencies>
##2.2 配置Log4j, 配置MyBatis## 在classpath创建一个用于配置log4j的配置文件log4j.properties, 再创建一个用于配置Mybatis的配置文件configuration.xml(文件可随便命名)。log4j的配置,我就很少说,这儿主要说一下configuration.xml:
<?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> <!-- 指定properties配置文件, 我这里面配置的是数据库相关 --> <properties resource="dbConfig.properties"></properties> <!-- 指定Mybatis使用log4j --> <settings> <setting name="logImpl" value="LOG4J"/> </settings> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <!-- 若是上面没有指定数据库配置的properties文件,那么此处能够这样直接配置 <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test1"/> <property name="username" value="root"/> <property name="password" value="root"/> --> <!-- 上面指定了数据库配置文件, 配置文件里面也是对应的这四个属性 --> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <!-- 映射文件,mybatis精髓, 后面才会细讲 --> <mappers> <mapper resource="com/dy/dao/userDao-mapping.xml"/> </mappers> </configuration>
##2.3 建立一张User表##
##2.4 编写代码##
package com.dy.entity; public class User { private int id; private String name; private String password; private int age; private int deleteFlag; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getDeleteFlag() { return deleteFlag; } public void setDeleteFlag(int deleteFlag) { this.deleteFlag = deleteFlag; } }
package com.dy.dao; import java.util.List; import com.dy.entity.User; public interface UserDao { public void insert(User user); public User findUserById (int userId); public List<User> findAllUsers(); }
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN" "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd"> <mapper namespace="com.dy.dao.UserDao"> <select id="findUserById" resultType="com.dy.entity.User" > select * from user where id = #{id} </select> </mapper>
userDao-mapping.xml至关因而UserDao的实现, 同时也将User实体类与数据表User成功关联起来
。
public class UserDaoTest { @Test public void findUserById() { SqlSession sqlSession = getSessionFactory().openSession(); UserDao userMapper = sqlSession.getMapper(UserDao.class); User user = userMapper.findUserById(2); Assert.assertNotNull("没找到数据", user); } //Mybatis 经过SqlSessionFactory获取SqlSession, 而后才能经过SqlSession与数据库进行交互 private static SqlSessionFactory getSessionFactory() { SqlSessionFactory sessionFactory = null; String resource = "configuration.xml"; try { sessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader(resource)); } catch (IOException e) { e.printStackTrace(); } return sessionFactory; } }
查看SqlSessionFactory.java开启事务:MyBatis对事务的处理相对简单,TransactionIsolationLevel中定义了几种隔离级别,并不支持内嵌事务这样较复杂的场景,同时因为其是持久层的缘故,因此真正在应用开发中会委托Spring来处理事务实现真正的与开发者隔离。分析事务的实现是个入口,借此能够了解很多JDBC规范方面的事情。
public interface SqlSessionFactory { SqlSession openSession(); // 事务默认自动提交 SqlSession openSession(boolean autoCommit); // 可传入 事务是否自动提交 SqlSession openSession(Connection connection); // 可传入 数据库链接 SqlSession openSession(TransactionIsolationLevel level); // 可传入 事务隔离级别 SqlSession openSession(ExecutorType execType); SqlSession openSession(ExecutorType execType, boolean autoCommit); SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level); SqlSession openSession(ExecutorType execType, Connection connection); Configuration getConfiguration(); }