#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(); }