MyBatis入門指南

cwf8 9年前發布 | 28K 次閱讀 MyBatis MyBatis3 持久層框架

MyBatis起源于 iBatis,iBatis是Clinton Begin在2002年發起的開源項目,于2010年6月16日從Apache的網站退役,并被Google Code托管,改名為MyBatis。MyBatis是一個支持普通SQL查詢、存儲過程和高級映射的優秀的持久層框架,它消除了幾乎所有的JDBC代 碼、對參數的手工設置以及對結果集繁瑣的處理,使用簡單的XML或注解(annotation)用于配置和映射,將接口和POJO(Plain Old Java Object)映射成數據庫中的記錄。MyBatis最新的版本可以在github上獲得,而它的文檔則可以通過下面的鏈接得到。

下載地址:https://github.com/mybatis/mybatis-3/releases

中文文檔:http://mybatis.github.io/mybatis-3/zh/index.html

相對于Hibernate這樣復雜的ORM(對象關系映射)框 架而言,MyBatis只能算得上是一種半自動化的ORM實現,像Hibernate這樣框架提供了對數據庫結構提供了較為完整的封裝,提供了從POJO 到數據庫表的全套映射機制。程序員往往只需定義好了POJO 到數據庫表的映射關系(通過XML或注解都可以完成),即可完成持久層操作;程序員甚至不需要熟練掌握的掌握SQL,因為Hibernate會自動生成對 應的SQL語句并通過JDBC代碼加以執行。大多數情況下這樣的機制無往不利,因此像Hibernate這樣的框架在ORM領域大有一統天下的勢頭。但 是,封裝得越好的東西,用戶能定制的操作就越少,在一些特定的場景下,Hibernate這樣的框架就未必能派上用場。例如:

  1. 系統的部分或全部數據來自現有數據庫,處于安全考慮,只對開發團隊提供幾條SQL語句(或存儲過程)以獲取所需數據,具體的表結構不予公開。
  2. 開發規范中要求,所有牽涉到業務邏輯部分的數據庫操作,必須在數據庫層由存儲過程實現。
  3. 系統數據處理量巨大,性能要求極為苛刻,這往往意味著我們必須通過經過高度優化的SQL語句(或存儲過程)才能達到系統性能設計指標。
    以上列舉的這幾條在金融行業的項目中可以說屢見不鮮,這個時候你會發現Hibernate幾乎無能為力,JDBC反而成為了不錯的選擇,但是JDBC中乏 味的字段讀取操作是非常惡心的。在這樣的場景下,半自動化的MyBatis剛好能滿足需求。</span> </p>

    使用MyBatis需要向你的項目中加入從上面的下載地址中下載到的JAR文件,當然,如果你使用了Maven,可以在pom.xml文件中加入對MyBatis的依賴。


    每一個MyBatis應 用都以一個SqlSessionFactory對象的實例為核心,SqlSessionFactory對象可以通過 SqlSessionFactoryBuilder對象來獲得,SqlSessionFactoryBuilder可以根據XML配置文件創建出 SqlSessionFactory對象。讓我們先看一下配置文件config.xml的內容:

        <?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>

     <typeAliases>  
         <typeAlias alias="User" type="com.lovo.entity.User" />  
         <typeAlias alias="Article" type="com.lovo.entity.Article" />  
     </typeAliases>  
    
     <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" />  
                 <property name="username" value="root" />  
                 <property name="password" value="123456" />  
             </dataSource>  
         </environment>  
     </environments>  
    
     <mappers>  
         <mapper resource="com/lovo/entity/User.xml" />  
         <mapper resource="com/lovo/entity/Article.xml" />  
     </mappers>  
    

    </configuration> </pre>
    可以通過SessionFactory對象的openSession()方法創建SqlSession對象,SqlSession 對象完全包含以數據庫為背景的所有執行SQL操作的方法,可以用SqlSession實例來直接執行已映射的SQL語句;當然,更簡潔的方式是使用接口來封裝對數據的操作。以下是實體類和映射文件。

    用戶類User.java:

        package com.lovo.entity;

    public class User {

     private String username;  
     private String password;  
     private String email;  
    
     public String getUsername() {  
         return username;  
     }  
    
     public void setUsername(String username) {  
         this.username = username;  
     }  
    
     public String getPassword() {  
         return password;  
     }  
    
     public void setPassword(String password) {  
         this.password = password;  
     }  
    
     public String getEmail() {  
         return email;  
     }  
    
     public void setEmail(String email) {  
         this.email = email;  
     }  
    
     @Override  
     public String toString() {  
         return "User [username=" + username + ", password=" + password  
                 + ", email=" + email + "]";  
     }  
    
    

    } </pre>
    用戶映射文件User.xml:

     <div>
          <pre class="brush:xml; toolbar: true; auto-links: false;">    <?xml version="1.0" encoding="UTF-8" ?>  
    

    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    ";

    <mapper namespace="com.lovo.dao.UserDao">

     <select id="findByUsername" parameterType="String" resultType="User">  
         select * from tb_user where username=#{username}  
     </select>  
    
     <select id="findAll" resultType="User">  
         select * from tb_user  
     </select>  
    
     <insert id="save" parameterType="User" keyProperty="username">  
         insert into tb_user (username, password, email) values (#{username}, #{password}, #{email})  
     </insert>  
    

    </mapper> </pre>

     </div>
    

    </div> </div>

    帖子類:

     <div>
          <pre class="brush:java; toolbar: true; auto-links: false;">    package com.lovo.entity;  
    
    

    import java.util.Date;

    public class Article {

     private int id;  
     private String content;  
     private User user;  
     private Date pubdate;  
    
     public int getId() {  
         return id;  
     }  
    
     public void setId(int id) {  
         this.id = id;  
     }  
    
     public String getContent() {  
         return content;  
     }  
    
     public void setContent(String content) {  
         this.content = content;  
     }  
    
     public User getUser() {  
         return user;  
     }  
    
     public void setUser(User user) {  
         this.user = user;  
     }  
    
     public Date getPubdate() {  
         return pubdate;  
     }  
    
     public void setPubdate(Date pubdate) {  
         this.pubdate = pubdate;  
     }  
    
     @Override  
     public String toString() {  
         return "Article [id=" + id + ", content=" + content + ", user=" + user.toString()  
                 + ", pubdate=" + pubdate + "]";  
     }  
}  </pre> <br />


</div> </div> </div> 帖子映射文件Article.xml:

    <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"
;

<mapper namespace="com.lovo.dao.ArticleDao">  
    <resultMap type="Article" id="resultArticle">  
        <id property="id" column="id"/>  
        <result property="content" column="content"/>  
        <result property="pubdate" column="pubdate"/>  
        <association property="user" javaType="User">  
            <id property="username" column="username" />  
            <result property="email" column="email"/>  
        </association>  
    </resultMap>  

    <select id="findAll" resultMap="resultArticle">  
        select t1.username, t1.email, t2.id, t2.content, t2.pubdate from tb_user as t1, tb_article as t2 where t1.username=t2.userid  
    </select>  
</mapper>  </pre> <br />


</div> </div> </div> UserDao接口:

    package com.lovo.dao;

import java.util.List;  

import com.lovo.entity.User;  

public interface UserDao {  

    public User findByUsername(String username);  

    public List<User> findAll();  

    public void save(User user);  
}  </pre> <br />


</div> </div> </div>

ArticleDao接口:

    package com.lovo.dao;

import java.util.List;  

import com.lovo.entity.Article;  

public interface ArticleDao {  

    public List<Article> findAll();  
}  </pre> </b>      </div>
</div>

</div>

測試代碼Test.java:

    package com.lovo.test;

import java.io.Reader;  
import java.util.List;  

import org.apache.ibatis.io.Resources;  
import org.apache.ibatis.session.SqlSession;  
import org.apache.ibatis.session.SqlSessionFactory;  
import org.apache.ibatis.session.SqlSessionFactoryBuilder;  

import com.lovo.dao.ArticleDao;  
import com.lovo.entity.Article;  

public class Test {  

    public static void main(String[] args) throws Exception {  
        Reader reader = Resources.getResourceAsReader("config.xml");  
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);  
        SqlSession session = sessionFactory.openSession();  
        try {  
            ArticleDao aDao = session.getMapper(ArticleDao.class);  
            List<Article> list = aDao.findAll();  
            for(Article a: list) {  
                System.out.println(a);  
            }  
            System.out.println("End!");  
        } finally {  
            session.close();  
        }  

    }  
}  </pre> <br />

</b>派生到我的代碼片 </div> </div> </div>
需要指出的是 SqlSessionFactoryBuilder類的對象一旦創建出SqlSessionFactory后就沒有用了,可以被丟棄;而 SqlSessionFactory對象一旦被創建,應該在整個應用程序執行期間都是存在的,最好是做成被其他程序共享的單例。對于 SqlSession,每 個線程都應該有它自己的SqlSession實例。SqlSession的實例不能被共享,因為它是線程不安全的,它的最佳作用范圍是請求或方法范圍。絕 對不能將SqlSession實例的引用放在一個類的靜態字段甚至是實例字段中,也絕不能SqlSession實例的引用放在任何類型的管理范圍中,例如 Serlvet的HttpSession中。不管你使用什么樣的Web框架,要考慮將SqlSession放在一個和 HTTP 請求對象相似的作用范圍內。換句話說,基于收到的 HTTP 請求,你可以打開 了一個 SqlSession,然后返回響應,就可以關閉它了。關閉Session很重要,最好的選擇是在finally代碼塊中關閉它。

 本文由用戶 cwf8 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!