##面向對象的世界與關係數據庫的鴻溝 Java語言是一門面向對象的程序設計語言,面向對象是從軟件工程的基本原則高內聚低耦合等理論基礎上發展起來的。java
正式編程語言與數據庫的不匹配,咱們沒有辦法在Java程序中像操做對象同樣的方式去操做關係型數據庫當中的數據。才須要一箇中間的映射技術,幫助咱們自動的實現對象與二元表之間的轉換。這種對象關係數據庫映射技術應運而生。mysql
##ORMgit
#MyBatis MyBatis官方網址github
在2010年這個項目由Apache基金會遷移到了Google Code並更名爲MyBatis。目前MyBatis在企業開發中應用很是普遍。本質上是ORM框架,可是與傳統ORM框架顯著不一樣的是,並不是創建Java對象到關係型數據庫表數據之間的映射關係。而是創建,對對象的操做方法到SQL語句之間的映射關係。因爲SQL語句自己是須要由SQL語句來編寫的。因此MyBatis的優點是可讓開發者使用關係型數據庫的全部的特性。好比存儲過程、視圖、複雜查詢等等。同時因爲MyBatis也讓開發者對執行的SQL得到了更多的控制,因此開發者能夠編寫更加高效率的SQL語句,來提升應用程序對數據庫的訪問效率。MyBatis是經過XML文件定義後端數據庫的,配置Java方法與後端映射關係的。sql
##MyBatis功能架構 MyBatis功能架構有三層, ###接口層 第一層是接口層,提供給外部使用的API接口。提供給咱們程序開發人員,開發人員使用本地API來操做數據庫,接口層接到調用請求後,將會把請求轉發給數據處理層進行執行。 ###數據庫處理層 第二層是數據處理層,主要負責具體SQL的查找、SQL解析、SQL執行和執行結果結果的映射處理。主要目的是根據調用請求來完成一次數據庫操做 ###基礎支持層 最後一層是基礎支撐層,主要負責最基礎的數據支持,數據庫的鏈接管理、事務管理、配置加載、緩存處理。都是共用的功能,把這些功能抽象出來做爲最基礎的組件。給上層的數據庫處理層提供最基礎的支撐。 數據庫
##MyBatis工做流機制 首先咱們須要在應用程序啓動的時候,加載XML文件。該XML文件定義了後端數據庫的地址,同時也定義了SQL與Java方法之間的映射關係apache
##MyBatis環境搭建 MyBatis下載最終版本編程
首先咱們須要下載MyBatis,解壓縮後查看目錄樹以下後端
mybatis/ └── mybatis-3.4.1 ├── LICENSE ├── NOTICE ├── lib │ ├── ant-1.9.6.jar │ ├── ant-launcher-1.9.6.jar │ ├── asm-5.0.4.jar │ ├── cglib-3.2.2.jar │ ├── commons-logging-1.2.jar │ ├── javassist-3.20.0-GA.jar │ ├── log4j-1.2.17.jar │ ├── log4j-api-2.3.jar │ ├── log4j-core-2.3.jar │ ├── ognl-3.1.8.jar │ ├── slf4j-api-1.7.21.jar │ └── slf4j-log4j12-1.7.21.jar ├── mybatis-3.4.1.jar └── mybatis-3.4.1.pdf 2 directories, 16 files
應用程序使用MyBatis須要把解壓縮當中的mybatis-3.x.x.jar放置到lib目錄下,更加推薦Maven方式,因爲MyBatis一樣基礎JDBC來訪問後端數據庫的,因此咱們一樣須要對應數據庫的JDBC驅動。api
###Maven
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.1</version> </dependency>
###Gradle
// https://mvnrepository.com/artifact/org.mybatis/mybatis compile group: 'org.mybatis', name: 'mybatis', version: '3.4.1'
##SqlSessionFactory 每一個MyBatis應用都是基於SqlSessionFactory實例爲中心的。經過SqlSessionFactory實例能夠獲取,將對象操做轉換成數據庫SQL的Session。咱們經過XML配置文件,能夠完成SqlSessionFactory的配置。首先咱們要來完成配置文件,整個XML配置文件包含了對MyBatis系統的核心配置。包括後端的數據庫鏈接實例數據源,和決定事務範圍事務處理的事務管理器。
###transactionManager 在transactionManager有type屬性,提供了兩個選項,jdbc和managed。
###dataSource 以後咱們要配置後端的數據庫源,與JDBC一致,主要包括4個屬性。分別是數據庫驅動、URL、用戶名、密碼。 ###官方文檔SqlSessionFactory的配置
<environments default="development"> <environment id="development"> <!-- 事務管理 --> <transactionManager type="JDBC"> <property name="..." value="..."/> </transactionManager> <!-- 數據庫鏈接數據源 --> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments>
##Java對象 ###構造對象 在配置完畢MyBatis後,咱們就須要對程序進行編寫,因爲MyBatis是Object Relation Mapping。咱們要定義Java對象,而後創建對象和對象操做SQL語句之間的映射關係。咱們定義的Java對象包括一些屬性。咱們這裏以User對象做爲示例。
package com.hava.mybatis.user.entity; /** * Created by zhanpeng on 09/10/2016. */ public class User { private Integer id; private String userName; private String corp; //公司 public User(Integer id,String userName,String corp) { this.id = id; this.userName = userName; this.corp = corp; } //Getter and Setter public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getCorp() { return corp; } public void setCorp(String corp) { this.corp = corp; } }
###構建接口 有了Java對象之後,咱們還須要定義對這個Java對象的操做。MyBatis與其餘與其餘傳統ORM框架是不一樣的。不是直接創建對象和關係型數據庫表數據的映射,而是採起更加靈活的方式,將對對象的操做與關係型數據庫的SQL語句創建關係。因此咱們須要定義一些對對象的操做。
咱們使用Java裏面的Interface接口的方式,來定義對對象的操做。
package com.hava.mybatis.user.entity; /** * Created by zhanpeng on 09/10/2016. */ public interface GetUserInfo { public User getUser(Integer id); public void addUser(User user); public void updateUser(User user); public void deleteUser(User user); }
##建立Java對象和SQL語句映射關係配置文件 Java對象接口與SQL語句的映射關係,映射關係也是經過配置文件來完成的。配置也是XML文件,配置文件中最重要的是包含Mapper的標籤。 ###namespace 標籤的namespace屬性的值是指向Java對象接口操做類的位置。 ###定義SQL語句 獲取數據庫中的信息,檢索數據庫獲取User信息,而後映射到Java的User對象中。因此咱們這裏的select id定義爲getUser,對應接口的具體方法。而後parameterType定義int,因爲咱們的方法參數爲int,resultType指向咱們定義的Java的User類。但願MyBatis把返回的結果自動轉化成定義爲Java對象。注意加完整路徑。
<?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.hava.mybatis.user.entity. GetUserInfo"> <!-- 定義SQL語句 --> <select id="getUser" parameterType="int" resultType="com.hava.mybatis.user.entity.User"> select id, userName,corp from user where id = #{id} </select> </mapper>
##註冊配置文件 咱們還須要將這個映射文件,加載到註冊到剛開始配置的SqlSessionFactory的配置文件中,咱們要在以前的配置文件中增長mappers的標籤。
##完成數據庫查詢 MyBatis完成數據庫查詢須要完成三個步驟,首先須要加載配置文件,而後建立一個SqlSessionFactory的實例。第二步經過SqlSessionFactory獲取sqlSession對象,sqlSession可以幫助咱們執行具體的SQL操做。最後一步就是利用Session進行查詢。
##MyBatis查詢實例 ###數據庫初始化
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userName` varchar(100) NOT NULL, `corp` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
手動添加了數據 ###修改pom.xml以支持xml運行
<!-- 因爲該項目須要添加在src下的xml文件進行運行則增長如下配置 --> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> </resources> </build>
###mybatis-conf.xml 上面的例子並無添加mybatis的DOCTYPE定義
<?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"> <!--<property name="..." value="..."/>--> </transactionManager> <!-- 數據庫鏈接數據源 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://192.168.1.200/test"/> <property name="username" value="root"/> <property name="password" value=""/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/hava/mybatis/user/entity/userMapper.xml" /> </mappers> </configuration>
###執行查詢過程
package com.hava.mybatis.user.service; import com.hava.mybatis.user.entity.GetUserInfo; import com.hava.mybatis.user.entity.User; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; /** * Created by zhanpeng on 09/10/2016. */ public class HelloMyBatis { public static void main(String [] args) { //1.聲明MyBatis的配置文件目錄 String resource = "mybatis-conf.xml"; //2.加載應用程序配置文件 InputStream inputStream = HelloMyBatis.class.getClassLoader().getResourceAsStream(resource); //3.建立SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); Configuration configuration = sqlSessionFactory.getConfiguration(); //Exception in thread "main" org.apache.ibatis.binding.BindingException: Type interface com.hava.mybatis.user.entity.GetUserInfo is already known to the MapperRegistry. // configuration.addMapper(GetUserInfo.class); //4.獲取Session SqlSession sqlSession = sqlSessionFactory.openSession(); try { //5.獲取操做類 GetUserInfo getUserInfo = sqlSession.getMapper(GetUserInfo.class); //6.完成查詢操做 User user = getUserInfo.getUser(1); System.out.println("[user.getUserName]:" + user.getUserName()); } finally { //7.關閉session sqlSession.close(); } } }
###注意 在執行演示語句發生異常
Exception in thread "main" org.apache.ibatis.binding.BindingException: Type interface com.hava.mybatis.user.entity.GetUserInfo is already known to the MapperRegistry. // configuration.addMapper(GetUserInfo.class);
說明若是在配置文件當中,已經mapper了接口文件,則不須要在代碼中再次mapper。 ###執行結果
[user.getUserName]:ZhangSan Process finished with exit code 0
#MyBatis優點與劣勢
#經過註解的方式
package com.hava.mybatis.user.repository; import com.hava.mybatis.user.entity.User; import org.apache.ibatis.annotations.Select; /** * Created by zhanpeng on 09/10/2016. */ public interface GetUserInfoAnnotation { @Select("select * from user where id = #{id}") public User getUser(int id); }
變動主程序
//1.聲明MyBatis的配置文件目錄 String resource = "mybatis-conf.xml"; //2.加載應用程序配置文件 InputStream inputStream = HelloMyBatis.class.getClassLoader().getResourceAsStream(resource); //3.建立SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); Configuration configuration = sqlSessionFactory.getConfiguration(); //Exception in thread "main" org.apache.ibatis.binding.BindingException: Type interface com.hava.mybatis.user.entity.GetUserInfo is already known to the MapperRegistry. configuration.addMapper(GetUserInfoAnnotation.class); //4.獲取Session SqlSession sqlSession = sqlSessionFactory.openSession(); try { //5.獲取操做類 // GetUserInfo getUserInfo = sqlSession.getMapper(GetUserInfo.class); //使用註解的方式 GetUserInfoAnnotation getUserInfo = sqlSession.getMapper(GetUserInfoAnnotation.class); //6.完成查詢操做 User user = getUserInfo.getUser(1); System.out.println("[user.getUserName]:" + user.getUserName()); } finally { //7.關閉session sqlSession.close(); }
##其餘數據庫操做
咱們在openSession添加了true,是因爲jdbc默認是以事務進行提交。可是在MyBatis是不一致的,默認會開啓事務。若是不設置true,都是以事務的形式提交。
###定義正刪改查接口
package com.hava.mybatis.user.repository; import com.hava.mybatis.user.entity.User; /** * Created by zhanpeng on 09/10/2016. */ public interface UserOp { public void addUser(User user); public void updateUser(User user); public void deleteUser(int id); public User getUser(int id); }
###添加定義文件 insert經過useGeneratedKeys獲取自增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="com.hava.mybatis.user.repository.UserOp"> <insert id="addUser" parameterType="com.hava.mybatis.user.entity.User" useGeneratedKeys="true" keyProperty="id"> insert into user (userName,corp) value(#{userName},#{corp}) </insert> <!-- 定義SQL語句 --> <select id="getUser" parameterType="int" resultType="com.hava.mybatis.user.entity.User"> select id, userName,corp from user where id = #{id} </select> <update id="updateUser" parameterType="com.micro.profession.mybatis.User"> update user set userName = #{userName} , corp = #{corp} where id = #{id} </update> <delete id="deleteUser" parameterType="com.micro.profession.mybatis.User"> delete from user where id = #{id} </delete> </mapper>
###修改Entity定義
public User(Integer id,String userName,String corp) public User(String userName,String corp)
必須均存在,用於MyBatis掃描和設置對象的屬性,得知MyBatis並非經過getter setter對對象的值進行設置。
package com.hava.mybatis.user.entity; /** * Created by zhanpeng on 09/10/2016. */ public class User { private Integer id; private String userName; private String corp; public User(Integer id,String userName,String corp) { this.id = id; this.userName = userName; this.corp = corp; } public User(String userName,String corp) { this.userName = userName; this.corp = corp; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getCorp() { return corp; } public void setCorp(String corp) { this.corp = corp; } }
###執行函數
package com.hava.mybatis.user.service; import com.hava.mybatis.user.entity.User; import com.hava.mybatis.user.repository.GetUserInfoAnnotation; import com.hava.mybatis.user.repository.UserOp; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; /** * Created by zhanpeng on 09/10/2016. */ public class HelloMyBatisMoreOp { public static void main(String[] args) { moreOp(); } public static void moreOp() { // 1. 聲明配置⽂件 String resource = "mybatis-conf.xml"; // 2. 加載應⽤配置⽂件 InputStream is = HelloMyBatisMoreOp.class.getClassLoader() .getResourceAsStream(resource); // 3. 建立SqlSessonFactory SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder() .build(is); SqlSession session = sessionFactory.openSession(true); try { // 5. 獲取操做類 UserOp userOp = session.getMapper(UserOp.class); User user = new User("XiaoMing", "Netease"); // 插⼊⽤戶 userOp.addUser(user); System.out.println(user.getId()); // 查詢⽤戶 user = userOp.getUser(user.getId()); System.out.println("userId:" + user.getId() + ", userName:" + user.getUserName() + ", corp:" + user.getCorp()); user.setUserName("LiMing"); // 更新⽤戶 userOp.updateUser(user); // 刪除⽤戶 userOp.deleteUser(user.getId()); } finally { // 7.關閉Session session.close(); } } }
###執行結果
4 userId:4, userName:XiaoMing, corp:Netease Process finished with exit code 0
###MyBatis的事務 若是openSession(true)則會自動提交sql,不會發生事務處理。若是採用默認方式openSession()
,則會開啓事務,進行處理,若是開啓事務,則須要手動進行提交工做。session.commit()
123