MyBatis其實是Ibatis3.0版本之後的持久化層框架【也就是和數據庫打交道的框架】! java
和數據庫打交道的技術有:mysql
原生的JDBC技術---> Spring的JdbcTemplate技術git
這些工具都是提供簡單的SQL語句的執行,可是和咱們這裏學的MyBatis框架還有些不一樣,框架是一整套的東西,例如事務控制,查詢緩存,字段映射等等。github
咱們用原生JDBC操做數據庫的時候都會通過:spring
編寫sql---->預編譯---->設置參數----->執行sql------->封裝結果sql
咱們之因此不使用原生的JDBC工具,是由於這些工具:數據庫
1.功能簡單,sql語句編寫在java代碼裏面【一旦修改sql,就須要將java及sql都要從新編譯!】這屬於硬編碼高耦合的方式。apache
2.咱們但願有開發人員本身編寫SQL語句,編程
而且但願SQL語句與java代碼分離,緩存
將SQL語句編寫在xml配置文件中,
實現數據表中記錄到對象之間的映射!
sql和java編碼分開,功能邊界清晰,一個專一於業務,一個專一於數據,可使用簡單的XML或註解用於配置和原始映射,將接口和Java的POJO映射成數據庫中的記錄,完成業務+底層數據庫的媒介!
原是Apache的一個開源項目iBatis, 2010年6月這 個項目由Apache Software Foundation 遷移到了 Google Code,隨着開發團隊轉投Google Code 旗下, iBatis3.x正式改名爲MyBatis ,代碼於 2013年11月遷移到Github(下載地址見後)。
iBatis一詞來源於「internet」和「abatis」的組合,是 一個基於Java的持久層框架。
iBatis提供的持久層框架包括SQL Maps和Data Access Objects、(DAO)
MyBatis 是支持定製化 SQL、存儲過程以及高級映射的優秀的持久層框架。
MyBatis 避免了幾乎全部的 JDBC 代碼和手動設置參數以及獲取結果集。
MyBatis可使用簡單的XML或註解用於配置和原始映射,將接口和Java的POJO(Plain Old JavaObjects,普通的Java對象)映射成數據庫中的記錄.
MyBatis是一個半自動化的輕量級的持久化層框架。
JDBC
– SQL夾在Java代碼塊裏,耦合度高致使硬編碼內傷
– 維護不易且實際開發需求中sql是有變化,頻繁修改的狀況多見
Hibernate和JPA
– 長難複雜SQL,對於Hibernate而言處理也不容易
– 內部自動生產的SQL,不容易作特殊優化。
– 基於全映射的全自動框架,大量字段的POJO進行部分映射時比較困難。 致使數據庫性能降低。
對開發人員而言,核心sql仍是須要本身優化,sql和java編碼分開,功能邊界清晰,一個專一業務、 一個專一數據。
https://github.com/mybatis/mybatis-3/
或者在百度直接搜索mybatis,而後找到github下的地址下載便可!
CREATE DATABASE mytabis; CREATE TABLE tbl_employee( id INT(11) PRIMARY KEY AUTO_INCREMENT, last_name VARCHAR(255), gender CHAR(1), email VARCHAR(255) )
而後插入兩條數據;
log4j-1.2.17.jar //固然須要注意的是:log4j的jar包是須要log4j.xml文件的
mybatis-3.4.1.jar
mysql-connector-java-5.1.37-bin.jar
<?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/mytabis"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <!-- 將咱們寫好的sql映射文件必定要註冊到全局配置文件中 --> <mappers> <mapper resource="EmployeeMapper.xml"/> </mappers> </configuration>
public class MyBatisTest { @Test public void test() throws IOException { //加載配置文件,將配置文件以流的形式傳入 String resource = "mytabis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); //獲取SqlSessionFactory實例 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession =null; try{ //2.獲取sqlSession實例,能直接執行已經映射的SQL語句 sqlSession= sqlSessionFactory.openSession(); //須要兩個參數,第一個參數是sql語句的惟一標識, //第二個參數是執行sql要用的參數 Employee employee = sqlSession.selectOne("com.neuedu.mybatis.EmployeeMapper.selectEmp",1); System.out.println(employee); }catch(Exception e){ }finally{ sqlSession.close(); } } }
<?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="com.neuedu.mybatis.EmployeeMapper"> <!-- namespace:名稱空間 id:sql語句的惟一標識 resultType:返回值類型 #{id}:接收參數傳遞過來的id值 --> <select id="selectEmp" resultType="com.neuedu.mybatis.bean.Employee"> select id,last_name lastName,gender,email from tbl_employee where id = #{id} </select> </mapper>
HelloWorld簡單版
– 建立一張測試表
–建立對應的javaBean
–建立mybatis配置文件,sql映射文件
– 測試
/**測試步驟: * 1.根據xml配置文件(全局配置文件)建立一個SqlSessionFactory對象 * 有數據源的一些運行環境信息 * 2.sql映射文件,配置了每個sql,以及sql的封裝規則等。 * 3.將sql映射文件註冊在全局配置文件中 * 4.寫代碼: * 1)根據全局配置文件獲得SqlSessionFactory * 2)使用sqlSession工廠,獲取到sqlSession對象使用它來執行增刪改查! * sqlSession就是表明和數據庫的一次會話!用完要關閉! * 3)使用sql的惟一標識告訴MyBatis執行哪一個sql。而sql都是保存 * 在sql映射文件中的。 */
上面那種開發方式適合老版本的mybatis使用者的開發方式!而新一批的mybatis使用者都是使用接口的方式,以下所示:
– 建立一個Dao接口
– 修改Mapper文件
– 測試
之前都是須要爲接口寫一個實現類,這是之前,可是此時,mybatis提供了接口能夠與sql配置文件動態綁定!
那如何將二者進行綁定呢?之前sql配置文件的namespace能夠隨便寫,如今就不能隨便寫了,需呀指定爲接口的全限定名!
而後此時接口和sql配置文件作了綁定,而後還要將select標籤的id和方法名進行綁定,
總結:
原生: Dao ==================> DaoImpl
mybatis: Mapper ================> xxMapper.xml
<!--將接口與xml文件進行綁定 --> EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
mybatis的全局配置文件:包含數據庫鏈接池信息,事務管理器信息等..系統運行環境信息。
sql映射文件:保存了每個sql語句的映射信息。
MyBatis 的配置文件包含了影響 MyBatis 行爲甚深的設置(settings)和屬性(properties)信息。文檔的頂層結構以下:
configuration 配置
properties 屬性
settings 設置
typeAliases 類型命名
typeHandlers 類型處理器
objectFactory 對象工廠
plugins 插件
environments 環境
environment 環境變量
transactionManager 事務管理器
dataSource 數據源
databaseIdProvider 數據庫廠商標識
mappers 映射器
<configuration> <!-- 1.mybatis可使用properties來引入外部properties配置文件的內容 resource:引入類路徑下的資源 url:引入網絡路徑或者磁盤路徑下的資源 --> <properties resource="jdbc.properties"></properties> <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.user}"/> <property name="password" value="${jdbc.passowrd}"/> </dataSource> </environment> </environments> <!-- 將咱們寫好的sql映射文件必定要註冊到全局配置文件中 --> <mappers> <mapper resource="EmployeeMapper.xml"/> </mappers> </configuration>
setting:用來設置每個設置
name:設置項名
value:設置項取值
舉例:駝峯式命名
<settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
做用:A type alias is simply a shorter name for a Java type
<!-- typeAliases:別名處理器,能夠爲咱們的java類型起別名,別名不區分大小寫 --> <typeAliases> <!-- typeAlias:爲某個java類型起別名 type:指定要起別名的類型全類名;默認別名就是類名小寫; alias:執行新的別名 --> <typeAlias type="com.neuedu.mybatis.bean.Employee"/> <!-- package:爲某個包下的全部類批量起別名 name:指定包名(爲當前包以及下面全部的後代包的每個類都起一個默認別名【類名小寫】) --> <package name="com.neuedu.mybatis.bean"/> <!-- 批量起別名的狀況下,使用@Alias註解爲某個類型指定新的別名 --> </typeAliases>
雖然有這麼多的別名可使用:可是建議你們仍是使用全類名,看SQL語句是怎麼被封裝爲JAVA 對象的時候簡單!
類型處理器:負責如何將數據庫的類型和java對象類型之間轉換的工具類
<!-- environments:環境們,mybatis能夠配置多種環境,default指定使用某種環境。能夠達到快速切換環境。 environment:配置一個具體的環境信息;必須有兩個標籤;id表明當前環境的惟一標識 transactionManager:事務管理器 type:事務管理器的類型;type="[JDBC|MANAGED]"),這兩個都是別名,在Configuration類中能夠查看具體類!可是Spring對事務的控制纔是最終的管理方案! 固然也能夠自定義事務管理器:只須要和人家同樣實現TransactionFactory接口,type指定爲全類名。 dataSource:數據源 type:type="[UNPOOLED|POOLED|JNDI]" 自定義數據源:實現DataSourceFactory接口,type也是全類名 可是咱們也說了,不管是事務管理器的配置仍是數據源的配置咱們都會使 用spring來作,這裏只須要了解一下便可! --> <environments default="development"> <environment id="test"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.user}"/> <property name="password" value="${jdbc.passowrd}"/> </dataSource> </environment> <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.user}"/> <property name="password" value="${jdbc.passowrd}"/> </dataSource> </environment> </environments>
MyBatis is able to execute different statements depending on your database vendor. The
MyBatis 能夠根據不一樣的數據庫廠商執行不一樣的語句
<databaseIdProvider type="DB_VENDOR"> <property name="SQL Server" value="sqlserver"/> <property name="DB2" value="db2"/> <property name="Oracle" value="" /> </databaseIdProvider>
Type: DB_VENDOR
–使用MyBatis提供的VendorDatabaseIdProvider解析數據庫 廠商標識。也能夠實現DatabaseIdProvider接口來自定義。
Property-name:數據庫廠商標識
Property-value:爲標識起一個別名,方便SQL語句使用
在mybatis的全局配置文件配置了這個以後,咱們只須要在sql映射文件中經過在執行語句的標籤上加一個屬性databaseId便可!
<select id="getEmployeeById" resultType="emp"> select * from tbl_employee where id = #{id} </select> <select id="getEmployeeById" resultType="emp" databaseId="mysql"> select * from tbl_employee where id = #{id} </select> <select id="getEmployeeById" resultType="emp" databaseId="oracle"> select * from tbl_employee where id = #{id} </select>
這樣在執行不一樣數據庫的時候,就會執行不一樣數據庫的語句了!固然如上所示:當有指定了databaseId屬性的和沒有指定databaseId屬性的,都有的狀況下那就按着有指定databaseId屬性的sql語句執行!
<environments default="dev_mysql"> <environment id="dev_oracle"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.user}"/> <property name="password" value="${jdbc.passowrd}"/> </dataSource> </environment> <environment id="dev_mysql"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.user}"/> <property name="password" value="${jdbc.passowrd}"/> </dataSource> </environment> </environments>
<!-- mappers:將sql映射註冊到全局配置中 --> <mappers> <!-- mapper:註冊一個sql映射 註冊配置文件: resource:引用類路徑下的sql映射文件 mybatis/mapper/EmployeeMapper.xml url:引用網絡路徑下或者磁盤路徑下的sql映射文件 url="file:///var/mappers/AuthorMapper.xml" 註冊接口 class:引用(註冊)接口 1.有sql映射文件,映射文件名必須和接口同名,而且放在與接口同一個目錄下; 2.沒有sql映射文件,全部的sql都是利用註解寫在接口上; 推薦: 比較重要的,複雜的Dao接口咱們來寫sql映射文件 不重要,見到的Dao接口爲了開發快速可使用註解 --> <mapper resource="mybatis/mapper/EmployeeMapper.xml"/> <mapper class="com.neuedu.mybatis.mapper.EmployeeMapperAnnotation"/> <!-- 批量註冊: 1.註解版確定是沒問題的 2.可是對於Mapper.xml映射文件和接口分開的,就須要保證在同一個包下且文件名相同了,不然找不到 --> <package name="com.neuedu.mybatis.mapper"/> </mappers>
映射文件指導着MyBatis如何進行數據庫增刪改查, 有着很是重要的意義;
cache –命名空間的二級緩存配置
cache-ref – 其餘命名空間緩存配置的引用。
resultMap – 自定義結果集映射
parameterMap – 已廢棄!老式風格的參數映射
sql –抽取可重用語句塊。
insert – 映射插入語句
update – 映射更新語句
delete – 映射刪除語句
select – 映射查詢語句
接口類:
public interface EmployeeMapper { public Employee getEmployeeById(Integer id); public void addEmp(Employee employee); public void updateEmp(Employee employee); public void deleteEmp(Integer id); }
在其對應的sql映射文件中:
<!--parameterType:能夠省略 ,且該sql語句最後不用寫分號--> <insert id="addEmp" parameterType="com.neuedu.mybatis.bean.Employee"> insert into tbl_employee(last_name,email,gender) values(#{lastName},#{gender},#{email}) </insert> <!-- public void updateEmp(Employee employee); --> <update id="updateEmp"> update tbl_employee set last_name=#{lastName},email=#{email},gender=#{gender} where id = #{id} </update> <!-- public void deleteEmp(Integer id); --> <delete id="deleteEmp"> delete from tbl_employee where id = #{id} </delete>
編寫測試單元:
/** * 測試增刪改 * 1.mybatis容許增刪改直接定義如下類型返回值 * Integer、Long、Boolean * 增刪改返回的是影響的多少行,只要影響0行以上就會返回true,0行如下就會返回false! * 直接在接口上寫這些包裝類或者基本類型就好, * 不必在sql映射文件中寫resultType,並且在sql映射文件中也沒有resultType標籤! * 2.咱們須要手動提交數據 *sqlSessionFactory.openSession();===>手動提交 *sqlSessionFactory.openSession(true);===>自動提交 */ @Test public void test02() { String resource = "mytabis-config.xml"; InputStream inputStream; SqlSession openSession = null; try { inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //1.獲取到的sqlSession不會自動提交數據,須要手動提交 openSession = sqlSessionFactory.openSession(); EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); mapper.addEmp(new Employee(null,"hah","email","1")); //手動提交 openSession.commit(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ //關閉會話 openSession.close(); } }
<!--parameterType:能夠省略 ,且該sql語句最後不用寫分號; 獲取自增主鍵的值: mysql支持自增主鍵:自增主鍵值的獲取,mybatis也是利用statement.getGeneratedKeys() useGeneratedKeys = "true";使用自增主鍵獲取主鍵值策略 keyProperty:指定對應的主鍵屬性,也就是mybatis獲取到主鍵值之後,將 這個值封裝給javaBean的哪一個屬性 --> <insert id="addEmp" parameterType="com.neuedu.mybatis.bean.Employee" useGeneratedKeys="true" keyProperty="id"> insert into tbl_employee(last_name,email,gender) values(#{lastName},#{gender},#{email}) </insert>
單個參數:mybatis不會作特殊處理
#{參數名}: 取出參數值
多個參數:mybatis會作特殊處理
多個參數會被封裝成一個map,
key:param1...paramN,或者參數的索引也能夠
value:傳入的參數值
#{}就是從map中獲取指定的key的值
異常:
org.apache.ibatis.binding.BingdingException:
Parameter 'id' not found.
Available parameters are [1,0,param1,param2]
操做:
方法:public Employee getEmployeeAndLastName(Integer id,String lastName);
取值:#{id},#{lastName}
命名參數:明確指定封裝參數時map的key:@param("id")
多個參數會被封裝成一個map,
key:使用@Param註解指定的值
value:參數值
#{指定的key}取出對應的參數值
POJO:
若是多個參數正好是咱們業務邏輯的數據模型,咱們就能夠直接傳入pojo;
#{屬性名}:取出傳入的pojo的屬性值
Map:
若是多個參數不是業務模型中的數據,沒有對應的pojo,不常用,爲了方便,咱們也能夠傳入map
#{key}:取出map中對應的值
List、Set
#這裏面的值也會被封裝到map集合中:
key:collection
值:對應的參數值
#{collection[0]}或#{list[0]}
#{}:能夠獲取map中的值或者pojo對象屬性的值
${}: 能夠獲取map中的值獲取pojo對象屬性的值
eg: select * from tbl_employee where id = ${id} and last_name = #{lastName}
preparing:select * from tbl_employee where id = 2 and last_name = ?
區別:
#{}:是以預編譯的形式,將參數設置到sql語句中,PreparedStatement;防止sql注入
${}:取出的值直接拼裝在sql語句中,會有安全問題;
大多狀況下,咱們取參數的值都應該去使用#{};
原生JDBC不支持佔位符的地方咱們就可使用${}進行取值,好比分表、排序;按照年份分表拆分
eg: select * from ${year}_salary where xxx;[表名不支持預編譯]
select * from tbl_employee order by ${f_name} ${order} :排序是不支持預編譯的!
Select元素來定義查詢操做。
Id:惟一標識符。
– 用來引用這條語句,須要和接口的方法名一致
parameterType:參數類型。
–能夠不傳,MyBatis會根據TypeHandler自動推斷
resultType:返回值類型。
– 別名或者全類名,若是返回的是集合,定義集合中元素的類型。不能和resultMap同時使用
eg:public List<Employee> getEmpsByLastNameLike(String lastName);
<!-- resultType:若是返回的是一個集合,要寫集合中元素的類型 --> <selecct id="getEmpsByLastNameLike" resultType="com.neuedu.mybatis.bean.Employee"> select * from tbl_employee where lastName like #{lastName} </select>
<!-- 返回一條記錄的map:key就是列名,值就是對應的值 --> public Map<String,Object> getEmpByIdReturnMap(Integer id); <select id="getEmpByIdReturnMap" resultType="map"> select * from tbl_employee where id = #{id} </select>
<!-- resultMap:自定義結果集映射規則 --> public Employee getEmployeById(Integer id); <!-- 自定義某個javaBean的封裝規則 type:自定義規則的java類型 id:惟一id方便引用 --> <resultMap type="com.neuedu.mybatis.bean.Employee" id = "myEmp"> <!-- 指定主鍵列的封裝規則 id定義主鍵列會有底層優化 column:指定是哪一列 property:指定對應的javaBean屬性 --> <id column="id" property = "id"> <!-- 定義普通列封裝規則 --> <result column="last_name" property="lastName"/> <!--其它不指定的列只要屬性名和列名會自動封裝,咱們只要寫resultMap就把所有的映射規則都寫上 --> </resultMap> <!--只須要在映射的地方映射一下就能夠了 -->