既然作了SpringMVC的小結,那就順便作個MyBatis的小結。java
MyBatis和Hibernate的執行流程差很少,都是加載配置文件 - 會話工廠建造器 - 會話工廠 - 會話 - 執行具體邏輯。redis
Configuration->SqlSessionFactoryBuilder/SessionFactoryBuilder->SqlSessionFactory/SessionFactory->SqlSession/Sessionsql
且都有懶加載、一二級緩存。數據庫
但MyBatis沒有Hibernate那麼抽象,學習起來相對簡單。只須要從其自帶的文檔MyBatis-User-Guide中搞清楚幾個概念便可。配置等更是能夠直接從文檔中複製。緩存
和Hibernate相似,MyBatis的執行須要配置文件(Cfg文件)和映射文件(通常稱爲Mapper文件)。session
配置文件無需多說,就是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="db.properties" /><!--加載數據庫信息--> <typeAliases> <package name="cn.larry.mybatis.po" /><!--類型別名,批量處理--> </typeAliases> <environments default="development"> <environment id="development"> <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> <mappers> <mapper resource="cn/larry/mybatis/mapper/UserMapper.xml" /><!--加載單個映射文件--> </mappers> </configuration>
映射文件,其實看樣例是最簡單的辦法:mybatis
<?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="test"> <!-- 需求:根據id查詢用戶信息 --> <!-- id:惟一標識。
parameterType:參數類型,輸入映射的類型。
resultType:返回結果類型,輸出映射的類型(老是對應表中一條記錄的類型)。
#{}:佔位符,若是傳遞的是基本類型,{}內的名稱:任意。
${}:鏈接符,若是傳遞的是基本類型,{}內的名稱:value。 --> <select id="queryUserById" parameterType="int" resultType="cn.larry.mybatis.po.User"> select * from user where id = #{id} </select> <!-- 根據username查詢用戶信息 --> <select id="queryUserListByUsername" parameterType="string" resultType="cn.larry.mybatis.po.User"> select * from user where username like '%${value}%' </select> <!-- 根據username查詢用戶信息 --> <select id="queryUserList" parameterType="string" resultType="cn.larry.mybatis.po.User"> select * from user </select> <!-- 添加用戶 --> <insert id="insertUser" parameterType="cn.larry.mybatis.po.User"> <selectKey keyProperty="id" resultType="int" order="AFTER"> select LAST_INSERT_ID() <!-- 插入後返回id,僅限於自增主鍵;select uuid()則能夠返回uuid類型的主鍵 --> </selectKey> insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address}) </insert> <!-- 更改用戶 --> <update id="updateUser" parameterType="cn.larry.mybatis.po.User"> update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id} </update> <!-- 刪除用戶--> <delete id="deleteUserById" parameterType="int"> delete from user where id=#{id} </delete> </mapper>
注意上面的標籤名,增刪改查的操做都有對應標籤(僅僅是爲了更好的辨識,本質上仍然是一堆SQL語句)。架構
另外,有人可能不理解鏈接符$的含意,其實模糊查詢那裏已經很明顯了。app
佔位符#是要做爲查詢的一個參數,獨立的參數;鏈接符$則能夠聯合已有的數據而後總體做爲一個參數。
你能夠寫成 '%${value}%',但不能寫成 '%#{value}%',由於#{value}是個獨立的參數,甚至無需引號。
至於標籤的屬性,看英文便可明白。
MyBatis的執行是直接調用映射文件中的標籤id:
User selectOne = sqlSession.selectOne("cn.larry.mybatis.mapper.UserMapper.queryUserById", 1); // 1是queryUserById須要的參數
傳統的Dao和DaoImpl是將SqlSessionFactory注入DaoImpl,經過接口方法調用映射文件中的標籤id,但這很麻煩,並且冗餘代碼太多。
@Override public User queryUserById(int id) throws Exception { SqlSession session = sqlSessionFactory.openSession(); User user = session.selectOne("test.queryUserById", id); return user; }
因此Mybatis提供了另外一種實現方式:Mapper代理。
這種方式只須要聲明接口,再編寫映射文件便可。
可是,它要求①接口名和映射文件名一致;②映射文件的namespace就是接口的全名稱(無擴展名);③接口方法要與映射文件中的標籤id一致。
<?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要和mapper的類全路徑名稱 --> <mapper namespace="cn.larry.mybatis.mapper.UserMapper"> <select id="queryAllUserList" resultType="user"> SELECT * FROM USER </select> </mapper>
package cn.larry.mybatis.mapper; import java.util.List; import cn.larry.mybatis.po.User; public interface UserMapper { public List<User> queryAllUserList(); }
具體調用:
UserMapper mapper = sqlSession.getMapper(UserMapper.class); // 指定Mapper對應的類(內部是JDK動態代理) List<User> queryAllUserList = mapper.queryAllUserList();
MyBatis提供了resultMap屬性,能夠將查詢的返回結果綁定到指定的屬性上。
其餘:
一對一:association。javaType。經過主鍵/id聯合。
一對多:collection。ofType。經過主鍵/id聯合。
多對多:由一對1、一對多嵌套聯合完成。
注意,標籤中使用extends="xxx_id",能夠繼承已有的mapper。
例如:Orders類中有User類還有OrdersDetail類,而一個mapper是查詢訂單和用戶的數據,另外一個mapper是查詢Orders、User以及OrdersDetail的數據,那麼後者能夠繼承前者,從而只須要添加對OrdersDetail的查詢便可。
延遲加載,就是按需加載,本質上就是將關聯的子查詢延後加載(未必是外鍵關聯的,同Hibernate)。默認關閉。
前提一:association或collection的內容能夠獨立出去,再使用select屬性引入,column屬性是關聯的外鍵。
前提二:settings配置。<setting name="lazyLoadingEnabled" value="true"/> (查找方法:直接查找標籤對應的類,查找其中的屬性)(全部標籤都對應某個類)
上面是標籤實現。
mybatis的緩存:
一級緩存,sqlSession級別的緩存,會話級別的緩存。語句和參數都相同。若是執行了commit操做,清空緩存。一級緩存的數據結構hashmap。(數據庫也有緩存)
二級緩存,mapper級別的緩存。只針對單表。重點:序列化。一級緩存始終開啓;二級緩存能夠設置開啓關閉。(cacheEnabled)想使用二級緩存,<cache></cache>便可。見說明。但,因爲一二級緩存都是mybatis的緩存,有侷限性,因此一般在分佈式架構中使用第三方緩存,如ehcache、redis、memcache等。ehcache1.7後,爲集羣提供了五種解決方案,rmi、jms、ehcache server、jgroups、terracotta。rmi不存在主從。若使用第三方緩存,緩存須要實現mybatis提供的Cache接口。加入jar包,設置配置文件,以及<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>便可。