MyBatis是Apache的一個開源項目,是一個基於Java的持久層框架。它支持普通SQL查詢、存儲過程以及高級映射。消除了幾乎全部的JDBC代碼,而且基本不須要手動去設置參數和獲取檢索結果。使用XML或者註解進行配置,可以映射基本數據元素、Map接口和POJO到數據庫。java
MyBatis的功能架構分三層:基礎支撐層、數據處理層、API接口層。mysql
基礎支撐層sql
負責最基本的功能支撐,包括鏈接管理、事務管理、配置加載和緩存處理。基礎支撐層爲上層的數據處理層提供了最基礎的支撐。數據庫
數據處理層緩存
負責具體的SQL查詢、SQL解析、SQL執行和執行結果的映射處理等。數據處理層的主要目的是根據調用的請求完成一次數據庫操做。mybatis
API接口層架構
提供給外部使用的接口API,經過這些API來操做數據庫。接口層接收到調用請求會馬上調用數據處理層來完成具體的操做。oracle
經過配置文件或註解,將SQL的配置信息加載成MappedStatement對象,存儲在內存中。app
調用MyBatis提供的API,並將請求傳遞給下層的數據處理層進行處理。框架
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper .//EN" "http://mybatis.org/dtd/mybatis--mapper.dtd"> <mapper namespace="com.demo.ssm.mapping.userMapper"> <select id="getUser" parameterType="int" resultType="User"> select * from user where id = #{id} </select> </mapper>
其中,namespace屬性用來定義mapper的命名空間。<select>
標籤中的id屬性用來標識sql語句,值必須惟一。parameterType屬性用來定義查詢時使用的參數類型。resultType屬性用來定義查詢返回的結果集類型。若是返回的結果集是個列表,應該定義resultMap類型。
<resultMap id="resultListUser" type="User"> <id column="id" property="id" /> <result column="userName" property="userName" /> <id column="userAge" property="userAge" /> </resultMap> <mapper namespace="com.demo.ssm.mapping.userMapper"> <select id="getUsers" parameterType="string" resultMap="resultListUser"> select * from user where username like #{userName} </select> </mapper>
<?xml version="." encoding="UTF-"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config .//EN" "http://mybatis.org/dtd/mybatis--config.dtd"> <configuration> <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:/mybatis" /> <property name="username" value="root" /> <property name="password" value="root" /> </dataSource> <environment> <environments> <mappers> <mapper resource="com.demo.ssm.mapping.userMapper.xml"> </mappers> </configuration>
在實際應用中,常常須要進行關聯查詢,如一對多、多對一等。這時,就須要在配置文件中使用<association>
標籤進行關聯。關聯查詢的配置有兩種方式:內部關聯和外部關聯。
<resultMap id="resultUserArticleList" type="Article"> <id property="id" column="aid" /> <result property="title" column="title" /> <result property="content" column="content" /> <association property="user" javaType="User"> <id property="id" column="id" /> <result property="userName" column="userName" /> <result property="userAge" column="userAge" /> </association> </resultMap> <select id="getUserArticles" parameterType="int" resultMap="resultUserArticleList"> select user.id,user.userName,user.userAge,article.id aid,article.title,article.content from user,article where user.id=article.userid and user.id=#{id} </select>
<resultMap type="User" id="resultListUser"> <id column="id" property="id" /> <result column="userName" property="userName" /> <result column="userAge" property="userAge" /> </resultMap> <resultMap id="resultUserArticleList" type="Article"> <id property="id" column="aid" /> <result property="title" column="title" /> <result property="content" column="content" /> <association property="user" javaType="User" resultMap="resultListUser" /> </resultMap> <select id="getUserArticles" parameterType="int" resultMap="resultUserArticleList"> select user.id,user.userName,user.userAge,article.id aid,article.title,article.content from user,article where user.id=article.userid and user.id=#{id} </select>
很顯然,第二種方式更容易達到複用的效果。
在實際應用中,若是查詢返回的結果記錄不少,就須要作物理分頁。不一樣的數據庫,對應不一樣的實現方法。mysql利用limit offset和pagesize來實現,而oracle利用rownum來實現。實現MyBatis的物理分頁。
<select id="getUserArticles" parameterType="params" resultMap="resultUserArticleList"> select user.id,user.userName,user.userAge,article.id aid,article.title,article.content from user,article where user.id=article.userid and user.id=#{id} limit #{offset},#{pagesize} </select>
這裏的parameterType是傳入的參數類或者Map,包含offset和pagesize,以及其餘須要的參數。相對來講,這是比較簡單的一種方式。
更通用的一種方式是使用插件進行分頁。使用插件的話,須要在MyBatis的配置文件中進行設置。
MyBatis的動態sql語句是基於OGNL表達式的,能夠很方便地在sql語句中實現某些邏輯。
<select id="dynamicIf" parameterType="User" resultType="User"> select * from user where 1 = 1 <if test="userName != null"> and userName = #{userName} </if> </select>
若是提供的userName參數不爲空,就爲sql語句動態添加userName=#{userName}的語句。
<select id="dynamicChoose" parameterType="User" resultType="User"> select * from user where 1 = 1 <choose> <when test="userName != null"> and userName = #{userName} </when> <otherwise> and userName = "sean" </otherwise> </choose> </select>
當userName不爲空時,爲sql語句動態添加userName=#{userName}。不然,爲sql語句動態添加userName="sean"語句。當條件知足時,再也不繼續判斷,直接跳出choose。當全部條件都不知足時,輸出otherwise中的內容。
<select id="dynamicWhere" parameterType="User" resultType="User"> select * from user <where> <if test="userName != null"> userName = #{userName} </if> </where> </select>
在where元素的地方輸出一個where,而且可以智能地處理and和or條件。主要用來簡化sql語句中where條件判斷。
<select id="dynamicTrim" parameterType="User" resultType="User"> select * from user <trim prefix="where" prefixOverrides="and | or"> <if test="userName != null"> userName = #{userName} </if> </trim> </select>
用來給包含的內容加上前綴或後綴,也能夠把包含內容的首部或尾部的某些內容覆蓋。一般能夠利用trim來代替where元素的功能。
<update id="dynamicSet" parameterType="User"> update user <set> <if test="userName != null"> userName = #{userName} </if> </set> where userId = #{userId} </update>
主要用於更新操做,在包含的語句前輸出一個set,功能和where元素基本相同。
主要用於構建in條件,能夠在sql語句中迭代一個集合。foreach元素主要有幾個屬性:
不一樣狀況下,collection屬性的值是不一樣的。若是傳入的是單參數且參數類型是一個List的時候,屬性值爲list。
<select id="dynamicForeachList" resultType="User"> select * from user where userId in <foreach collection="list" index="index" item="item" open="(" separator="," close=")"> #{item} </foreach> </select>
若是傳入的是單參數且參數類型是一個Array的時候,屬性值爲array。
<select id="dynamicForeachArray" resultType="User"> select * from user where userId in <foreach collection="array" index="index" item="item" open="(" separator="," close=")"> #{item} </foreach> </select>
若是傳入的是多個參數時,將參數封裝成一個Map,屬性值爲map裏的key。
<select id="dynamicForeachMap" resultType="User"> select * from user where userName like "%"#{userName}"%" and userId in <foreach collection="ids" index="index" item="item" open="(" separator="," close=")"> #{item} </foreach> </select>
因爲MyBatis應用程序須要大量的配置文件,若是徹底手工配置,工做量巨大。MyBatis官方推出一個代碼生成工具mybatis-generator-core的jar包,以便提升效率。
代碼生成工具主要有幾個功能:
首先須要建立一個配置文件,進行生成工具的各類設置。
<generatorConfiguration> <!-- 配置mysql驅動jar包路徑 --> <classPathEntry location="" <context id="mysql_tables" targetRuntime="MyBatis3"> <!-- 控制生成代碼中的註釋 --> <commentGenerator> <property name="suppressAllComments" value="true" /> <property name="suppressDate" value="true" /> </commentGenerator> <!-- 數據庫鏈接 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=utf8" userId="root" password="root"> </jdbcConnection> <javaTypeResolver> <property name="forceBigDecimals" value="false" /> </javaTypeResolver> <!-- model層 --> <javaModelGenerator targetPackage="com.demo.ssm.model" targetProject="src"> <property name="enableSubPackages" value="true" /> <property name="trimStrings" value="true" /> </javaModelGenerator> <!-- mapper映射文件 --> <sqlMapGenerator targetPackage="com.demo.ssm.mapper" targetProject="src"> <property name="enableSubPackages" value="true" /> </sqlMapGenerator> <!-- mapper接口 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.demo.ssm.inter" targetProject="src"> <property name="enableSubPackages" value="true" /> </javaClientGenerator> <!-- 指定要生成代碼的數據庫表 --> <table schema="mybatis" tableName="user" domainObjectName="User" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"> </table> </context> </generatorConfiguration>
而後建立一個代碼生成類,用於生成代碼。
public class GenMain { public static void main(String[] args) { List<String> warnings = new ArrayList<String>(); boolean overwrite = true; String genCfg = "/mbgConfiguration.xml"; File configFile = new File(GenMain.class.getResource(genCfg).getFile()); ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = null; try { config = cp.parseConfiguration(configFile); } catch (IOException e) { e.printStackTrace(); } catch (XMLParserException e) { e.printStackTrace(); } DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = null; try { myBatisGenerator = new MyBatisGenerator(config, callback, warnings); } catch (InvalidConfigurationException e) { e.printStackTrace(); } try { myBatisGenerator.generate(null); } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } }