1)MyBatis是Apache的一個開源項目iBatis, 2010年6月這個項目由Apache Software Foundation 遷移到了Google Code,隨着開發團隊轉投Google Code旗下, iBatis3.x 正式改名爲MyBatis ,代碼於2013年11月遷移到Githubjava
2)iBatis一詞來源於「internet」和「abatis」的組合,是一個基於Java的持久層框架。 iBatis 提供的持久層框架包括SQL Maps和Data Access Objects(DAO)mysql
下載網址git
https://github.com/mybatis/mybatis-3/github
2.Hibernate和JPAsql
3.MyBatis數據庫
1.導入MyBatis框架的jar包、Mysql驅動包、log4j的jar包apache
2.導入log4j.xml配置文件編程
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"> <param name="Encoding" value="UTF-8" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" /> </layout> </appender> <logger name="java.sql"> <level value="debug" /> </logger> <logger name="org.apache.ibatis"> <level value="info" /> </logger> <root> <level value="debug" /> <appender-ref ref="STDOUT" /> </root> </log4j:configuration>
3.建立測試表api
-- 建立庫 CREATE DATABASE test_mybatis; -- 使用庫 USE test_mybatis; -- 建立表 CREATE TABLE tbl_employee( id INT(11) PRIMARY KEY AUTO_INCREMENT, last_name VARCHAR(50), email VARCHAR(50), gender CHAR(1) );
4.建立javaBean數組
public class Employee { private Integer id ; private String lastName; private String email ; private String gender ; public Integer getId() { return id; } //...生成get、set 、toString }
5.建立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> <!-- 數據庫鏈接環境的配置 --> <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:3306/mybatis_1129" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> <!-- 引入SQL映射文件,Mapper映射文件 --> <mappers> <mapper resource="EmployeeMapper.xml" /> </mappers> </configuration>
6.建立Mybatis的Mapper映射文件
<?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="suibian"> <select id="selectEmployee" resultType="com.hbuas.myabtis.helloWorld.Employee"> select id ,last_name lastName ,email ,gender from tbl_employee where id = #{id} <!-- select * from tbl_employee where id = #{id} --> </select> </mapper>
7.編寫測試類
@Test public void test() throws Exception { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); System.out.println(sqlSessionFactory); SqlSession session = sqlSessionFactory.openSession(); try { Employee employee = session.selectOne("suibian.selectEmployee", 1001); System.out.println(employee); } finally { session.close(); } }
使用mapper接口開發是秉承Mybatis倡導的面向接口編程
1.編寫Mapper接口,實現兩個綁定:
public interface EmployeeMapper { public Employee getEmployeeById(Integer id ); }
3.編寫測試類
獲取Mybatis操做數據庫的會話對象SqlSession,經過getMapper()獲取接口的動態代理實現類
@Test public void test() throws Exception{ String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder() .build(inputStream); SqlSession session = sqlSessionFactory.openSession(); try { //Mapper接口:獲取Mapper接口的 代理實現類對象 EmployeeMapper mapper = session.getMapper(EmployeeMapper.class); Employee employee = mapper.getEmployeeById(1006); System.out.println(employee); } finally { session.close(); } }
MyBatis 的配置文件包含了影響 MyBatis 行爲甚深的設置(settings)和屬性(properties)信息。
配置文件結構以下:
configuration 配置 |
屬性信息嚴格按照上面順序配置。
<properties> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/test_mybatis" /> <property name="username" value="root" /> <property name="password" value="1234" /> </properties>
properties的做用並不僅僅是這樣,你能夠建立一個資源文件,名爲jdbc.properties的文件,將四個鏈接字符串的數據在資源文件中經過鍵值 對(key=value)的方式放置,不要任何符號,一條佔一行
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis_1129 jdbc.username=root jdbc.password=1234
<!-- properties: 引入外部的屬性文件 resource: 從類路徑下引入屬性文件 url: 引入網絡路徑或者是磁盤路徑下的屬性文件 --> <properties resource="db.properties" ></properties>
<environments default="oracle"> <environment id="mysql"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </dataSource> </environment> </environments>
<settings> <setting name="cacheEnabled" value="true"/> <setting name="lazyLoadingEnabled" value="true"/>開啓延遲加載 <setting name="multipleResultSetsEnabled" value="true"/> <setting name="useColumnLabel" value="true"/> <setting name="useGeneratedKeys" value="false"/> <setting name="autoMappingBehavior" value="PARTIAL"/> <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/> <setting name="defaultExecutorType" value="SIMPLE"/> <setting name="defaultStatementTimeout" value="25"/> <setting name="defaultFetchSize" value="100"/> <setting name="safeRowBoundsEnabled" value="false"/> <setting name="mapUnderscoreToCamelCase" value="false"/>將下劃線映射成駝峯 <setting name="localCacheScope" value="SESSION"/> <setting name="jdbcTypeForNull" value="OTHER"/> <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/> </settings>
1.類型別名是爲 Java 類型設置一個短的名字,能夠方便咱們引用某個類。
<typeAliases> <typeAlias type="com.hbuas.mybatis.beans.Employee" alias="emp"/> </typeAliases>
alias屬性能夠不寫,不寫默認就是類名切不區分大小寫。
2.類不少的狀況下,能夠批量設置別名這個包下的每個類建立一個默認的別名,就是簡單類名小寫
<typeAliases> <package name="com.hbuas.mybatis.beans"/> </typeAliases>
<environments default="oracle"> <environment id="mysql"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </dataSource> </environment> <environment id="oracle"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${orcl.driver}" /> <property name="url" value="${orcl.url}" /> <property name="username" value="${orcl.username}" /> <property name="password" value="${orcl.password}" /> </dataSource> </environment> </environments>
cache – 給定命名空間的緩存配置。
cache-ref – 其餘命名空間緩存配置的引用。
resultMap – 是最複雜也是最強大的元素,用來描述如何從數據庫結果集中來加載對象。
parameterMap – 已廢棄!老式風格的參數映射。內聯參數是首選,這個元素可能在未來被移除,這裏不會記錄。
sql – 可被其餘語句引用的可重用語句塊。
insert – 映射插入語句
update – 映射更新語句
delete – 映射刪除語句
select – 映射查詢語
public interface EmpMapper { //根據eid查詢一個員工信息 Emp getEmpByEid(String eid); //獲取全部的員工信息 List<Emp> getAllEmp(); //添加員工信息 void addEmp(Emp emp); //修改員工信息 void updateEmp(Emp emp); //刪除員工信息 Boolean deleteEmp(String eid); }
<mapper namespace="com.hbuas.mapper.EmpMapper"> <!-- Emp getEmpByEid(String eid); --> <select id="getEmpByEid" resultType="Emp"> select eid,ename,age,sex from emp where eid = #{eid} </select> <!-- List<Emp> getAllEmp(); --> <select id="getAllEmp" resultType="Emp"> select eid,ename,age,sex from emp </select> <!-- void addEmp(Emp emp); --> <insert id="addEmp"> insert into emp values(null,#{ename},#{age},#{sex}) </insert> <!-- void updateEmp(Emp emp); --> <update id="updateEmp"> update emp set ename = #{ename}, age = #{age}, sex = #{sex} where eid = #{eid} </update> <!-- void deleteEmp(String eid); --> <delete id="deleteEmp"> delete from emp where eid = #{eid} </delete> </mapper>
<insert id="insertEmployee" parameterType="com.hbuas.mybatis.beans.Employee" databaseId="mysql" useGeneratedKeys="true" keyProperty="id"> insert into tbl_employee(last_name,email,gender) values(#{lastName},#{email},#{gender}) </insert>
<insert id="insertEmployee" parameterType="com.atguigu.mybatis.beans.Employee" databaseId="oracle"> <selectKey order="BEFORE" keyProperty="id" resultType="integer"> select employee_seq.nextval from dual </selectKey> insert into orcl_employee(id,last_name,email,gender) values(#{id},#{lastName},#{email},#{gender}) </insert>
myBatis獲取參數值的兩種方式:
1.單個普通類型參數:能夠接受基本類型,包裝類型,字符串類型等。
2.多個參數
任意多個參數,都會被MyBatis從新包裝成一個Map傳入。Map的key是param1,param2,或者0,1…,值就是參數的值
#{}:#{0}、#{1}、#{param1}、#{param2}
${}:${value}、${ param2 },可是要注意${}的單引號問題
3.命名參數
爲參數使用@Param起一個名字,MyBatis就會將這些參數封裝進map中,key就是咱們本身指定的名字。#{},${}均可以經過健名獲取值,注意單引號問題。
4.POJO
當這些參數屬於咱們業務POJO時,咱們直接傳遞POJO屬性名獲取值,可是注意${}單引號問題。
5.Map
咱們也能夠封裝多個參數爲map,直接傳遞
6.Collection/Array
會被MyBatis封裝成一個map傳入, List以list爲鍵,Array以array爲鍵
<!-- <resultMap>:自定義映射,處理複雜的表關係 <id column="eid" property="eid"/> <id>:設置主鍵的映射關係,column設置字段名,property設置屬性名 <result column="ename" property="ename"/> <result>:設置非主鍵的映射關係,column設置字段名,property設置屬性名 -->
<!-- 此種方式用的比較少--> <resultMap type="Emp" id="empMap"> <id column="eid" property="eid"/> <result column="ename" property="ename"/> <result column="age" property="age"/> <result column="sex" property="sex"/> <result column="did" property="dept.did"/> <result column="dname" property="dept.dname"/> </resultMap> <!-- List<Emp> getAllEmp(); --> <select id="getAllEmp" resultMap="empMap"> select e.eid,e.ename,e.age,e.sex,e.did,d.dname from emp e left join dept d on e.did = d.did </select>
以級聯屬性的方式封裝對象.
<resultMap type="Emp" id="empMap"> <id column="eid" property="eid"/> <result column="ename" property="ename"/> <result column="age" property="age"/> <result column="sex" property="sex"/> <association property="dept" javaType="Dept"> <id column="did" property="did"/> <result column="dname" property="dname"/> </association> </resultMap>
<select id="getEmployeeAndDeptStep" resultMap="myEmpAndDeptStep"> select id, last_name, email,gender,d_id from tbl_employee where id =#{id} </select> <resultMap type="com.hbuas.mybatis.beans.Employee" id="myEmpAndDeptStep"> <id column="id" property="id" /> <result column="last_name" property="lastName"/> <result column="email" property="email"/> <result column="gender" property="gender"/> <association property="dept" select="com.hbuas.mybatis.dao.DepartmentMapper.getDeptById" column="d_id" fetchType="eager"> </association> </resultMap>
Settings中進行以下的配置:
<!-- 開啓延遲加載 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 設置加載的數據是按需仍是所有 --> <setting name="aggressiveLazyLoading" value="false"/>
專門用來處理一對多和多對多的關係
<resultMap type="Dept" id="deptMap"> <id column="did" property="did"/> <result column="dname" property="dname"/> <!-- <collection>:處理一對多和多對多的關係 ofType:指集合中的類型,不須要指定javaType --> <collection property="emps" ofType="Emp"> <id column="eid" property="eid"/> <result column="ename" property="ename"/> <result column="age" property="age"/> <result column="sex" property="sex"/> </collection> </resultMap>
對於查詢部門信息而且將對應的全部的員工信息也查詢出來的需求,就能夠經過分步的方式完成查詢。
<!-- List<Emp> getEmpListByDid(String did); --> <select id="getEmpListByDid" resultType="Emp"> select eid,ename,age,sex from emp where did = #{did} </select> <resultMap type="Dept" id="deptMapStep"> <id column="did" property="did"/> <result column="dname" property="dname"/> <collection property="emps" select="com.hbuas.mapper.EmpDeptMapper.getEmpListByDid" column="{did=did}" fetchType="eager"></collection> </resultMap> <!-- Dept getOnlyDeptByDid(String did); --> <select id="getOnlyDeptByDid" resultMap="deptMapStep"> select did,dname from dept where did = #{did} </select>
1.在<association> 和<collection>標籤中均可以設置fetchType,指定本次查詢是否要使用延遲加載。默認爲 fetchType=」lazy」 ,若是本次的查詢不想使用延遲加載,則可設置爲fetchType=」eager」.
2.fetchType能夠靈活的設置查詢是否須要使用延遲加載,而不須要由於某個查詢不想使用延遲加載將全局的延遲加載設置關閉.
MyBatis動態SQL簡介
<select id="getEmpListByMoreTJ1" resultType="Emp"> select eid,ename,age,sex,did from emp <where> <if test="eid != null"> and eid = #{eid} </if> <if test="ename != null and ename != ''"> and ename = #{ename} </if> <if test="age != null"> and age = #{age} </if> <if test="sex == 1 or sex == 0"> and sex = #{sex} </if> </where> </select>
<select id="getEmpListByMoreTJ1" resultType="Emp"> select eid,ename,age,sex,did from emp <trim prefix="where" suffixOverrides="and"> <if test="eid != null"> eid = #{eid} and </if> <if test="ename != null and ename != ''"> ename = #{ename}and </if> <if test="age != null"> age = #{age}and </if> <if test="sex == 1 or sex == 0"> sex = #{sex} </if> </where> </select>
set 主要是用於解決修改操做中SQL語句中可能多出逗號的問題
<update id="updateEmpByConditionSet"> update tbl_employee <set> <if test="lastName!=null && lastName!="""> last_name = #{lastName}, </if> <if test="email!=null and email.trim()!=''"> email = #{email} , </if> <if test=""m".equals(gender) or "f".equals(gender)"> gender = #{gender} </if> </set> where id =#{id} </update>
choose 主要是用於分支判斷,相似於java中的switch case,只會知足全部分支中的一個
<select id="getEmpsByConditionChoose" resultType="com.hbuas.mybatis.beans.Employee"> select id ,last_name, email,gender from tbl_employee <where> <choose> <when test="id!=null"> id = #{id} </when> <when test="lastName!=null"> last_name = #{lastName} </when> <when test="email!=null"> email = #{email} </when> <otherwise> gender = 'm' </otherwise> </choose> </where> </select>
<!-- <foreach collection="" item="" close="" open="" separator="" index=""></foreach> 對一個數組或集合進行遍歷 collection:指定要遍歷的集合或數組 item:設置別名 close:設置循環體的結束內容 open:設置循環體的開始內容 separator:設置每一次循環之間的分隔符 index:若遍歷的是list,index表明下標;若遍歷的是map,index表明鍵 -->
<delete id="deleteMoreByList"> delete from emp where eid in <foreach collection="eids" item="eid" separator="," open="(" close=")"> #{eid} </foreach> </delete>
sql 標籤是用於抽取可重用的sql片斷,將相同的,使用頻繁的SQL片斷抽取出來,單獨定義,方便屢次引用.
<!-- <sql id=""></sql>:設置一段SQL片斷,即公共SQL,能夠被當前映射文件中全部的SQL語句所訪問 <include refid="empColumns"></include>:訪問某個SQL片斷 --> <sql id="empColumns">select eid,ename,age,sex,did from emp </sql> <select id="getEmpByEid" resultType="Emp"> <include refid="empColumns"></include> where eid = #{eid} </select>
MyBatis 包含一個很是強大的查詢緩存特性,它能夠很是方便地配置和定製。緩存能夠極大的提高查詢效率,MyBatis系統中默認定義了兩級緩存(一級緩存、二級緩存)默認狀況下,只有一級緩存(SqlSession級別的緩存,也稱爲本地緩存)開啓。
/** mybatis中的一級緩存默認開啓,是SqlSession級別的 即同一個SqlSession對於一個sql語句,執行以後就會存儲在緩存中,下次執行相同的sql,直接從緩存中取 一級緩存失效的狀況: * 不一樣的SqlSession對應不一樣的一級緩存 * 同一個SqlSession可是查詢條件不一樣 * 同一個SqlSession兩次查詢期間執行了任何一次增刪改操做,會自動將緩存清空 * 同一個SqlSession兩次查詢期間手動清空了緩存 */
/** * mybatis的二級緩存默認不開啓,須要設置: * 一、在覈心配置文件<settings>中,加入配置:<setting name="cacheEnabled" value="true"/> * 二、須要使用二級緩存的映射文件處使用cache配置緩存<cache /> * 三、注意:POJO須要實現Serializable接口 * 注意:二級緩存在 SqlSession 關閉或提交以後纔會生效 * 1)全局setting的cacheEnable: 配置二級緩存的開關,一級緩存一直是打開的 * 2)select標籤的useCache屬性: 配置這個select是否使用二級緩存。一級緩存一直是使用的 * 3)sql標籤的flushCache屬性: 增刪改默認flushCache=true。sql執行之後,會同時清空一級和二級緩存。 查詢默認 flushCache=false。 * 4)sqlSession.clearCache():只是用來清除一級緩存 */
二級緩存相關的屬性
LRU – 最近最少使用的:移除最長時間不被使用的對象。
FIFO – 先進先出:按對象進入緩存的順序來移除它們。
SOFT – 軟引用:移除基於垃圾回收器狀態和軟引用規則的對象。
WEAK – 弱引用:更積極地移除基於垃圾收集器狀態和弱引用規則的對象。
默認的是 LRU。
默認狀況是不設置,也就是沒有刷新間隔,緩存僅僅調用語句時刷新
表明緩存最多能夠存儲多少個對象,太大容易致使內存溢出
true:只讀緩存;會給全部調用者返回緩存對象的相同實例。所以這些對象不能被修改。這提供了很重要的性能優點。
false:讀寫緩存;會返回緩存對象的拷貝(經過序列化)。這會慢一些,可是安全,所以默認是 false。
爲了提升擴展性。MyBatis定義了緩存接口Cache。咱們能夠經過實現Cache接口來自定義二級緩存
EhCache 是一個純Java的進程內緩存框架,具備快速、精幹等特色,是Hibernate中默認的CacheProvider
整合EhCache緩存的步驟
1.導入ehcache包,以及整合包,日誌包
2.編寫ehcache.xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <!-- 磁盤保存路徑 --> <diskStore path="D:\hbuas\ehcache" /> <defaultCache maxElementsInMemory="1000" maxElementsOnDisk="10000000" eternal="false" overflowToDisk="true" timeToIdleSeconds="120" timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> </defaultCache> </ehcache> <!-- 屬性說明: l diskStore:指定數據在磁盤中的存儲位置。 l defaultCache:當藉助CacheManager.add("demoCache")建立Cache時,EhCache便會採用<defalutCache/>指定的的管理策略 如下屬性是必須的: l maxElementsInMemory - 在內存中緩存的element的最大數目 l maxElementsOnDisk - 在磁盤上緩存的element的最大數目,如果0表示無窮大 l eternal - 設定緩存的elements是否永遠不過時。若是爲true,則緩存的數據始終有效,若是爲false那麼還要根據timeToIdleSeconds,timeToLiveSeconds判斷 l overflowToDisk - 設定當內存緩存溢出的時候是否將過時的element緩存到磁盤上 如下屬性是可選的: l timeToIdleSeconds - 當緩存在EhCache中的數據先後兩次訪問的時間超過timeToIdleSeconds的屬性取值時,這些數據便會刪除,默認值是0,也就是可閒置時間無窮大 l timeToLiveSeconds - 緩存element的有效生命期,默認是0.,也就是element存活時間無窮大 diskSpoolBufferSizeMB 這個參數設置DiskStore(磁盤緩存)的緩存區大小.默認是30MB.每一個Cache都應該有本身的一個緩衝區. l diskPersistent - 在VM重啓的時候是否啓用磁盤保存EhCache中的數據,默認是false。 l diskExpiryThreadIntervalSeconds - 磁盤緩存的清理線程運行間隔,默認是120秒。每一個120s,相應的線程會進行一次EhCache中數據的清理工做 l memoryStoreEvictionPolicy - 當內存緩存達到最大,有新的element加入的時候, 移除緩存中element的策略。默認是LRU(最近最少使用),可選的有LFU(最不常使用)和FIFO(先進先出) -->
3.配置cache標籤
<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>