摘要: 本文結合《Spring源碼深度解析》來分析Spring 5.0.6版本的源代碼。若有描述錯誤之處,歡迎指正。
MyBatis本是Apache的一個開源項目iBatis,2010年這個項目由Apache Software Foundation遷移到了Google Code,並且改名為MyBatis。
MyBatis是支持普通SQL查詢,存儲過程和高級映射的優秀持久層框架。MyBatis消除了幾乎所有的JDBC代碼和參數的手工設置以及結果集的檢索。MyBatis使用簡單的XML或注解用於配置和原始映射,將接口和Java的POJOs映射成數據庫中的記錄。
盡管我們接觸更多的是MyBatis與Spring的整合使用,但是MyBatis有它自己的獨立使用方法,了解其獨立使用的方法套路對分析Spring整合MyBatis非常有幫助,因為Spring無非就是將這些功能進行封裝以簡化我們的開發流程。MyBatis獨立使用包括以下幾步。
(1)建立PO。
用於對數據庫中數據的映射,是程序員更關注於對Java類的使用而不是數據庫的操作。
public class User { private Long id; private String username; private Integer age; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username == null ? null : username.trim(); } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
(2)建立Mapper。
數據庫操作的映射文件,也就是我們常說的DAO,用於映射數據庫的操作,也可以通過配置文件指定方法對應的SQL語句或者直接使用Java提供的注解方式進行SQL指定。
public interface UserMapper { int insert(User record); User selectByPrimaryKey(Long id); }
(3)建立配置文件。
配置文件主要用於配置程序中可變性高的配置,一個偏大的程序一定會存在一些經常會變化的變量,如果每次變化都需要改變源碼那會是非常糟糕的設計,所以,我們看到各種各樣的框架或者應用的時候都免不了要配置配置文件,MyBatis中的配置文件主要封裝在configuration中,配置文件的基本結構如下圖所示。
configuration | 根元素 |
properties | 定義配置外在化 |
settings | 一些全局性的配置 |
typeAliases | 為一些類定義別名 |
typeHandlers | 定義類型處理,也就是定義Java類型與數據庫中的數據類型之間的轉換關系 |
objectFactory | 用於指定結果集對象的實例是如何創建的 |
mappers | 指定映射文件或映射類 |
environments | 環境 |
environment | 配置MyBatis的環境 |
transactionManager | 事務管理器 |
dataSource | 數據源 |
plugins | MyBatis的插件,插件可以修改MyBatis內部的運行規則 |
讀者如果對上面的各個配置具體使用方法感興趣,可以進一步查閱相關資料,這里只舉出最簡單的實例以方便讀者快速回顧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> <!--屬性--> <properties resource="properties/database.properties"/> <!--設置--> <settings> <setting name="cacheEnabled" value="false"/> <setting name="useGeneratedKeys" value="true"/> <setting name="defaultExecutorType" value="REUSE"/> </settings> <!--類型命名--> <typeAliases> <typeAlias alias="User" type="org.cellphone.uc.repo.po.User"/> </typeAliases> <!--配置環境--> <environments default="development"> <!--環境變量--> <environment id="development"> <!--事務管理器--> <transactionManager type="jdbc"/> <!--數據源--> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <!--映射器--> <mappers> <mapper resource="mapper/UserMapper.xml"/> </mappers> </configuration>
(4)建立映射文件。
對應於MyBatis全局配置中的mappers配置屬性,主要用於建立對應數據庫操作接口的SQL映射。MyBatis會將這里設定的SQL與對應的Java接口相關聯,以保證在MyBatis中調用接口的時候會到數據庫中執行相應的SQL來簡化開發。
<?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.cellphone.uc.repo.mapper.UserMapper"> <resultMap id="BaseResultMap" type="org.cellphone.uc.repo.po.User"> <!-- WARNING - @mbg.generated This element is automatically generated by MyBatis Generator, do not modify. This element was generated on Sat Apr 21 15:38:35 CST 2018. --> <id column="id" jdbcType="BIGINT" property="id" /> <result column="username" jdbcType="VARCHAR" property="username" /> <result column="age" jdbcType="INTEGER" property="age" /> </resultMap> <sql id="Base_Column_List"> <!-- WARNING - @mbg.generated This element is automatically generated by MyBatis Generator, do not modify. This element was generated on Sat Apr 21 15:38:35 CST 2018. --> id, username, age </sql> <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap"> <!-- WARNING - @mbg.generated This element is automatically generated by MyBatis Generator, do not modify. This element was generated on Sat Apr 21 15:38:35 CST 2018. --> select <include refid="Base_Column_List" /> from user where id = #{id,jdbcType=BIGINT} </select> <insert id="insert" parameterType="org.cellphone.uc.repo.po.User"> <!-- WARNING - @mbg.generated This element is automatically generated by MyBatis Generator, do not modify. This element was generated on Sat Apr 21 15:38:35 CST 2018. --> insert into user (id, username, password, sex, age, status, create_tm ) values (#{id,jdbcType=BIGINT}, #{username,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER} ) </insert> </mapper>
(5)建立測試類。
至此我們已經完成了MyBatis的建立過程,接下來的工作就是對之前的所有工作進行測試,以便直接查看MyBatis為我們提供的結果。
public class MyBatisUtils { private final static SqlSessionFactory SQL_SESSION_FACTORY; static { String resource = "mybatis-config.xml"; Reader reader = null; try { reader = Resources.getResourceAsReader(resource); } catch (IOException e) { e.printStackTrace(); } SQL_SESSION_FACTORY = new SqlSessionFactoryBuilder().build(reader); } public static SqlSessionFactory getSqlSessionFactory() { return SQL_SESSION_FACTORY; } }
public class MapperTest { static SqlSessionFactory sqlSessionFactory = null; static { sqlSessionFactory = MyBatisUtils.getSqlSessionFactory(); } @Test public void testAdd() { SqlSession sqlSession = sqlSessionFactory.openSession(); try { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = new User(); user.setUsername("hello"); user.setAge(5); userMapper.insert(user); sqlSession.commit(); // 這里一定要提交,不然數據進不去數據庫中 } finally { sqlSession.close(); } } @Test public void getUser() { SqlSession sqlSession = sqlSessionFactory.openSession(); try { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = userMapper.selectByPrimaryKey(32L); System.out.println("name: " + user.getUsername() + "| age: " + user.getAge()); } finally { } } }
注意,這里在數據庫中設定了id自增策略,所以插入的數據會直接在數據庫中賦值,當執行測試后如果數據表為空,那么在表中會出現一條我們插入的數據,並會在查詢時將此數據查出。