MyBatis框架介紹

mybatis框架

 

1.1 mybatis是?

 

mybatis是一個持久層的框架,是apache下的頂級項目。java

mybatis託管到goolecode下,再後來託管到github(https://github.com/mybatis/mybatis-3/releases)mysql

 

mybatis讓程序將主要精力放在sql上,經過mybatis提供的映射方式,自由靈活生成(半自動化,大部分須要程序員編寫sql)知足須要sql語句。git

 

mybatis能夠將向 preparedStatement中的輸入參數自動進行輸入映射,將查詢結果集靈活映射成java對象。(輸出映射程序員

 

1.2 mybatis框架


入門程序

2.1 需求

根據用戶id(主鍵)查詢用戶信息github

根據用戶名稱模糊查詢用戶信息spring

添加用戶sql

刪除 用戶數據庫

更新用戶apache

 

2.2 環境

java環境:jdk1.7.0_72安全

eclipseindigo

mysql5.1

 

mybatis運行環境(jar包):

從https://github.com/mybatis/mybatis-3/releases下載,3.2.7版本

 

 

lib下:依賴包

mybatis-3.2.7.jar:核心 包

mybatis-3.2.7.pdf,操做指南

 

加入mysql的驅動包

 

2.3 log4j.properties

 

 

2.4 工程結構

 

 

2.5 SqlMapConfig.xml

配置mybatis的運行環境,數據源、事務等。

 

 

 

 

2.6 根據用戶id(主鍵)查詢用戶信息

 

2.6.1 建立po

 

 

2.6.2 映射文件

映射文件命名:

User.xml(原始ibatis命名),mapper代理開發映射文件名稱叫XXXMapper.xml,好比:UserMapper.xmlItemsMapper.xml

在映射文件中配置sql語句。 

Id:表示映射文件的sql,將sql語句封裝到mappedStatement對象中,因此id成爲statementid

resultType:將單條結果映射成java對象

 

 

2.6.3 SqlMapConfig.xml加載映射文件

sqlMapConfig.xml中加載User.xml:

 

 

2.6.4 程序編寫

 

 

 

2.7 根據用戶名稱模糊查詢用戶信息

 

2.7.1 映射文件

 

使用User.xml,添加根據用戶名稱模糊查詢用戶信息的sql語句。

 

 

 

2.7.2 程序代碼

 

 

 

1paramterType---輸入參數類型,resultType---返回java類型

2)注意sql語句中 佔位符---#{value}  

字符串拼接---’%${value}%’  可能引發sql注入(好比輸入value=OR 1=1 OR

(3)selectOne查詢一條,selectList返回多條結果

 

 

2.8 添加用戶

 

2.8.1 映射文件

在 User.xml中配置添加用戶的Statement

 

 

 

2.8.2 程序代碼

 

 

 

2.8.3 自增主鍵返回

mysql自增主鍵,執行insert提交以前自動生成一個自增主鍵。

經過mysql函數獲取到剛插入記錄的自增主鍵:

LAST_INSERT_ID()

 

insert以後調用此函數。

 

修改insertUser定義:

 

 

 

2.8.4 非自增主鍵返回(使用uuid())

 

使用mysqluuid()函數生成主鍵,須要修改表中id字段類型爲string,長度設置成35位。

 

執行思路:

先經過uuid()查詢到主鍵,將主鍵輸入 到sql語句中。

 

執行uuid()語句順序相對於insert語句以前執行。

 

 

 

經過oracle的序列生成主鍵:

 

<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">

SELECT 序列名.nextval()

</selectKey>

insert into user(id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address})

 

 

2.9 刪除用戶

2.9.1 映射文件

 

 

2.9.2 代碼:

 

2.10 更新用戶

2.10.1 映射文件

 

 

2.10.2 代碼

 

 

 

 

2.11 總結

 

2.11.1 parameterType

在映射文件中經過parameterType指定輸入 參數的類型

2.11.2 resultType

在映射文件中經過resultType指定輸出結果的類型

 

2.11.3 #{}${}

 

#{}表示一個佔位符號,#{}接收輸入參數,類型能夠是簡單類型,pojohashmap

若是接收簡單類型,#{}中能夠寫成value或其它名稱。

#{}接收pojo對象值,經過OGNL讀取對象中的屬性值,經過屬性.屬性.屬性...的方式獲取對象屬性值。

 

${}表示一個拼接符號,會引用sql注入,因此不建議使用${}

${}接收輸入參數,類型能夠是簡單類型,pojohashmap

若是接收簡單類型,${}中只能寫成value

${}接收pojo對象值,經過OGNL讀取對象中的屬性值,經過屬性.屬性.屬性...的方式獲取對象屬性值。

 

 

 

2.11.4 selectOneselectList

 

selectOne表示查詢出一條記錄進行映射。若是使用selectOne能夠實現使用selectList也能夠實現(list中只有一個對象)。

 

selectList表示查詢出一個列表(多條記錄)進行映射。若是使用selectList查詢多條記錄,不能使用selectOne

 

若是使用selectOne報錯:

org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 4

 

 

2.12 mybatishibernate本質區別和應用場景

 

hibernate:是一個標準ORM框架(對象關係映射)。入門門檻較高的,不須要程序寫sqlsql語句自動生成了。

sql語句進行優化、修改比較困難的。

應用場景:

適用與需求變化很少的中小型項目,好比:後臺管理系統,erpormoa。。

 

mybatis專一是sql自己,須要程序員本身編寫sql語句,sql修改、優化比較方便。mybatis是一個不徹底 的ORM框架,雖然程序員本身寫sqlmybatis 也能夠實現映射(輸入映射、輸出映射)。

應用場景:

適用與需求變化較多的項目,好比:互聯網項目。

 

企業進行技術選型,以低成本 高回報做爲技術選型的原則,根據項目組的技術力量進行選擇。

 

mybatis開發dao的方法

 

3.1 SqlSession使用範圍

 

3.1.1 SqlSessionFactoryBuilder

 經過SqlSessionFactoryBuilder建立會話工廠SqlSessionFactory

將SqlSessionFactoryBuilder當成一個工具類使用便可,不須要使用單例管理SqlSessionFactoryBuilder。

在須要建立SqlSessionFactory時候,只須要new一次SqlSessionFactoryBuilder便可。

 

 

3.1.2 SqlSessionFactory

經過SqlSessionFactory建立SqlSession,使用單例模式管理sqlSessionFactory(工廠一旦建立,使用一個實例)。

 

未來mybatisspring整合後,使用單例模式管理sqlSessionFactory

 

 

3.1.3 SqlSession

SqlSession是一個面向用戶(程序員)的接口。

SqlSession中提供了不少操做數據庫的方法:如:selectOne(返回單個對象)selectList(返回單個或多個對象)、。

 

SqlSession是線程不安全的,在SqlSesion實現類中除了有接口中的方法(操做數據庫的方法)還有數據域屬性。

 

SqlSession最佳應用場合在方法體內,定義成局部變量使用。

 

3.2 原始dao開發方法(程序員須要寫dao接口和dao實現類)

3.2.1 思路

程序員須要寫dao接口和dao實現類。

須要向dao實現類中注入SqlSessionFactory,在方法體內經過SqlSessionFactory建立SqlSession

 

3.2.2 dao接口

 

3.2.3 dao接口實現類

public class UserDaoImpl implements UserDao {

 

// 須要向dao實現類中注入SqlSessionFactory

// 這裏經過構造方法注入

private SqlSessionFactory sqlSessionFactory;

 

public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {

this.sqlSessionFactory = sqlSessionFactory;

}

 

@Override

public User findUserById(int id) throws Exception {

SqlSession sqlSession = sqlSessionFactory.openSession();

 

User user = sqlSession.selectOne("test.findUserById", id);

 

// 釋放資源

sqlSession.close();

 

return user;

 

}

 

@Override

public void insertUser(User user) throws Exception {

SqlSession sqlSession = sqlSessionFactory.openSession();

 

//執行插入操做

sqlSession.insert("test.insertUser", user);

 

// 提交事務

sqlSession.commit();

 

// 釋放資源

sqlSession.close();

 

}

 

@Override

public void deleteUser(int id) throws Exception {

SqlSession sqlSession = sqlSessionFactory.openSession();

 

//執行插入操做

sqlSession.delete("test.deleteUser", id);

 

// 提交事務

sqlSession.commit();

 

// 釋放資源

sqlSession.close();

 

}

 

}

 

3.2.4 測試代碼:

 

 

3.2.5 總結原始 dao開發問題

1dao接口實現類方法中存在大量模板方法,設想可否將這些代碼提取出來,大大減輕程序員的工做量。

 

2、調用sqlsession方法時將statementid硬編碼了

 

3、調用sqlsession方法時傳入的變量,因爲sqlsession方法使用泛型,即便變量類型傳入錯誤,在編譯階段也不報錯,不利於程序員開發。

 

 

 

3.3 mapper代理方法(程序員只須要mapper接口(至關 於dao接口))

 

3.3.1 思路(mapper代理開發規範)

 

程序員還須要編寫mapper.xml映射文件

程序員編寫mapper接口須要遵循一些開發規範,mybatis能夠自動生成mapper接口實現類代理對象。

 

開發規範:

1、在mapper.xmlnamespace等於mapper接口地址

 

 

2mapper.java接口中的方法名和mapper.xmlstatementid一致

 

3mapper.java接口中的方法輸入參數類型和mapper.xmlstatementparameterType指定的類型一致。

 

4mapper.java接口中的方法返回值類型和mapper.xmlstatementresultType指定的類型一致。

 

 

 

 

 

總結:

以上開發規範主要是對下邊的代碼進行統一輩子成:

 

User user = sqlSession.selectOne("test.findUserById", id);

sqlSession.insert("test.insertUser", user);

。。。。

 

 

3.3.2 mapper.java

 

3.3.3 mapper.xml

 

 

3.3.4 SqlMapConfig.xml中加載mapper.xml

 

 

 

3.3.5 測試

 

 

 

3.3.6 一些問題總結

3.3.6.1 代理對象內部調用selectOneselectList

 

若是mapper方法返回單個pojo對象(非集合對象),代理對象內部經過selectOne查詢數據庫。

 

若是mapper方法返回集合對象,代理對象內部經過selectList查詢數據庫。

 

 

3.3.6.2 mapper接口方法參數只能有一個是否影響系統 開發

mapper接口方法參數只能有一個,系統是否不利於擴展維護。

 

系統 框架中,dao層的代碼是被業務層公用的。

即便mapper接口只有一個參數,可使用包裝類型的pojo知足不一樣的業務方法的需求。

 

注意:持久層方法的參數能夠包裝類型、map。。。,service方法中建議不要使用包裝類型(不利於業務層的可擴展)。