MyBatis 學習筆記


MyBatis 學習筆記:
官網: http://www.mybatis.org , http://code.google.com/p/mybatis/

=========================
用到的資料和工具:  
=========================
1. 從官網下載用戶手冊:  MyBatis 3 User Guide Simplified Chinese.pdf
2. 幾個主要的參考教程:
   mybatis3入門學習筆記 (五star推薦, 我直接使用了該作者的SessionFactoryUtil類)
   http://blessht.iteye.com/blog/1097005   
   
   有關 sql xml 的寫法, 可以參考下面2個文章, 講的很清晰
   cms項目第9天(上)-mybatis框架
   http://blog.sina.com.cn/s/blog_6bcb0a8c0100q6ub.html
   cms項目第9天(下)-mybatis框架
   http://blog.sina.com.cn/s/blog_6bcb0a8c0100q6ud.html
   
3. 下載MyBatis最新的運行包, mybatis-3.0.6-bundle.zip
4. 下載MyBatis最新的代碼生成工具包, mybatis-generator-core-1.3.1-bundle.zip
5. 下載MyBatis的config和map以及mybatis-generator的DTD文件.
    mybatis 仍使用過時的DTD作為XML的schema, 我們寫的XML每個標簽必須按照DTD中的聲明順序寫,不然會報XML invalidated錯誤. 不知道MyBatis為什么不用XSD來代替DTD?
    http://mybatis.org/dtd/mybatis-3-config.dtd
    http://mybatis.org/dtd/mybatis-3-mapper.dtd
    http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd
6. 准備Eclipse XML Editor插件(Visual studio僅僅支持xsd, 不支持dtd), 每次在Eclipse要安裝這個插件, 總是花好長時間來google找個插件的名稱, 這次將安裝過程記錄下來.
   在Eclipse的菜單Install new software中, 選擇下面的site:
      Indigo - http://download.eclipse.org/releases/indigo
   然后選擇  Web, XML, Java EE and OSGi Enterprise Development    
   最后選擇  Eclipse XML Editors and Tools
   

=========================
使用 mybatis-generator 根據table, 可生成 POJO/SQL map XML和DAO mapper代碼,
注意: 該工具並不負責生成 mybatis 主config 文件.
=========================   
要使用mybatis-generator工具, 首先需要手動寫一個generator的配置文件, 可以參考 mybatis-generator-core-1.3.1-bundle.zip包里的文檔, 假定我們已經寫好了名為generatorConfig.xml的配置文件 , 使用mybatis-generator方法是:
 
1. 首次生成POJO/DAO Interface/xml mapping的命令,
  java -jar mybatis-generator-core-x.x.x.jar -configfile generatorConfig.xml -overwrite  
2. 如有幾個表重構結構后, 可以使用如下命令, 重新生成相關的 POJO/DAO Interface/xml mapping文件,
  java -jar mybatis-generator-core-x.x.x.jar -configfile generatorConfig.xml -overwrite   -tables  table1,table2,table3
 
以下是一個mybatis-generator配置文件的內容,
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "../res/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <classPathEntry
        location="D://corp_files/trunk/workspace/MyProject/lib/postgresql-9.1-901.jdbc4.jar" />

    <context id="MyProject" targetRuntime="MyBatis3" >
        
        <commentGenerator>
             <property name="suppressAllComments" value="true" />
        </commentGenerator>

        <jdbcConnection driverClass="org.postgresql.Driver"
            connectionURL="jdbc:postgresql://localhost:5432/postgres" userId="postgres"
            password="abc123!">
        </jdbcConnection>

        <javaTypeResolver>
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

        <javaModelGenerator targetPackage="MyProject.model"
            targetProject="c:/src">
            <property name="enableSubPackages" value="true" />
            <property name="trimStrings" value="false" />
        </javaModelGenerator>

        <sqlMapGenerator targetPackage="MyProject.xml"
            targetProject="c:/src">
            <property name="enableSubPackages" value="true" />
        </sqlMapGenerator>

        <javaClientGenerator type="XMLMAPPER"
            targetPackage="MyProject.dao" targetProject="c:/src">
            <property name="enableSubPackages" value="true" />
        </javaClientGenerator>
        
        
        <table tableName="user_info" schema="public" domainObjectName="UserBean">
        </table>
        <table tableName="dept_info" schema="public" domainObjectName="DeptBean">
        </table>

    </context>
</generatorConfiguration>

 


=========================
編寫mybatis config 文件:  
=========================
基本作用就是配置JDBC連接的有關信息,比如URL、用戶名、密碼等等, 下面的配置文件是從網上拷貝了一份.
<?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 type="org.leadfar.mybatis.Person" alias="Person" />
    </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/mybatis" />
                <property name="username" value="root" />
                <property name="password" value="leadfar" />
            </dataSource>
        </environment>

    </environments>

    <!-- 映射文件定位 -->
    <mappers>
        <mapper resource="org/leadfar/mybatis/PersonMapper.xml" />
    </mappers>

</configuration>

 


=========================
使用 mybatis-generator 生成 POJO/SQL map XML和DAO mapper代碼
=========================
首先看一下生成的代碼,  POJO很簡單, 就不貼了,

生成的 DAO interface(有刪減)
public interface cronMapper {
    int deleteByPrimaryKey(String cronCode);
    //....
}


生成的 sql mapping 配置文件(有刪減)
<?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="MyProject.dao.public.cronMapper" >
<delete id="deleteByPrimaryKey" parameterType="java.lang.String" >
 
    delete from public.caw_cron
    where cron_code = #{cronCode,jdbcType=VARCHAR}
  </delete>
</mapper>  


從上面看出, 生成的 DAO 代碼其實都是 interface (如cronMapper), 而不是具體的 class, 那么現在就有一個疑問了, 我們該如何使用這個接口呢? 是否需要自己寫代碼來實現該接口呢?

答案是, 不需要! 我們直接使用 MyBatis的 SqlSession的 getMapper()方法就可以動態的獲得一個已經實現了 cronMapper 接口的對象. 見下面的代碼,   

如何使用 cronMapper 接口, 進行DAO 操作,
SqlSession session = sqlSessionFactory.openSession();
try {
    cronMapper mapper = session.getMapper(cronMapper.class);
    mapper.deleteByPrimaryKey("your_code")
    // do other work
} finally {
    session.close();
}


至於MyBatis的 SqlSession的 getMapper(), 為什么能為我們返回一個實現 cronMapper 接口的對象, 應該是使用了JDK的動態代理或者攔截技術吧.

在知道了如何使用 MyBatis 生成的 DAO 接口代碼后, 還有一個問題是, 是否還需要自己的DAO代碼層? 我覺得仍然需要, 原因有兩個:
1. 如果直接在Business Logic層(BLL)使用 Mybatis的sqlSessionFactory.openSession(), BLL代碼顯得不太簡潔, 如果我們在自己的的DAO層封裝了openSession()代碼, BLL層代碼就簡潔多了.
2. 很多時候我們的查詢會復雜一些, 比如在權限管理模塊, 一個用戶對象可以有多個角色對象. 我們期望的方案是, 在用戶對象內部有一個角色對象集合. MyBatis 可通過 resultMap 支持這種 one-to-many 的 mapping, 其后果是sql mapping 的xml要復雜很多. 我個人覺得, 這種情況, 不如不用mybatis這些高級特性, MyBatis僅僅完成UserEntityDAO和RoleEntityDAO的簡單mapping, 然后自己實現一個User DAO對象, 將UUserEntityDAO和RoleEntityDAO在代碼中做封裝.  


=========================
可以將MyBatis的sqlSessionFactory和 getSession()封裝在一個工具類中. 這樣自定義的DAO類可能很方便地使用.
摘自 http://blessht.iteye.com/blog/1097005  
=========================
public class SessionFactoryUtil {  
    
    private static final String RESOURCE = "com/mybatisdemo/config/Configuration.xml";  
    private static SqlSessionFactory sqlSessionFactory = null;  
    private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();  
 
    static {  
        Reader reader = null;  
        try {  
            reader = Resources.getResourceAsReader(RESOURCE);  
        } catch (IOException e) {  
            throw new RuntimeException("Get resource error:"+RESOURCE, e);  
        }  
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);  
    }  
      
    /**
     * Function  : 獲得SqlSessionFactory
     */  
    public static SqlSessionFactory getSqlSessionFactory(){     
        return sqlSessionFactory;     
    }  
      
    /**
     * Function  : 重新創建SqlSessionFactory
     */  
    public static void rebuildSqlSessionFactory(){  
        Reader reader = null;  
        try {  
            reader = Resources.getResourceAsReader(RESOURCE);  
        } catch (IOException e) {  
            throw new RuntimeException("Get resource error:"+RESOURCE, e);  
        }  
 
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);  
    }  
      
    /**
     *  
     * Function  : 獲取sqlSession
     */  
    public static SqlSession getSession(){  
        SqlSession session = threadLocal.get();  
          
        if(session!=null){  
            if(sqlSessionFactory == null){  
                getSqlSessionFactory();  
            }  
            //如果sqlSessionFactory不為空則獲取sqlSession,否則返回null  
            session = (sqlSessionFactory!=null) ? sqlSessionFactory.openSession(): null;  
        }  
          
        return session;  
    }  
      
    /**
     * Function  : 關閉sqlSession
     */  
    public static void closeSession(){  
        SqlSession session = threadLocal.get();  
        threadLocal.set(null);  
        if(session!=null){  
            session.close();  
        }  
    }  
}  


=========================
問題1: 如何mapping 數據表的char(1)和java 的 boolean類型
摘自 http://javaeenotes.blogspot.com/2011/10/mybatis-and-oracle-database.html (通過bing 搜索引擎可以看到cache)
=========================

針對這種需求, 在SQL XML中, 不能直接使用resultType, 必須有個resultMap, 在對應的boolean字段節點上, 指定typeHandler.
<resultMap id="BaseResultMap" type="MyProject.model.public.cron" >
    <!--
      WARNING - @mbggenerated
      This element is automatically generated by MyBatis Generator, do not modify.
      This element was generated on Wed Nov 30 17:34:29 CST 2011.
    -->
    <id column="job_code" property="jobCode" jdbcType="VARCHAR" />
    <result column="enabled" property="enabled" jdbcType="CHAR" typeHandler="com.xxx.sample.BooleanTypeHandler" />
    <result column="description" property="description" jdbcType="VARCHAR" />
  </resultMap>
 
 
 
實現一個com.xxx.sample.BooleanTypeHandler類,
import org.apache.ibatis.type.JdbcType;  
import org.apache.ibatis.type.TypeHandler;  

/**
 * BooleanTypeHandler類, 處理完成char(1)與Boolean類型的轉換
 */
public class BooleanTypeHandler implements TypeHandler<Boolean>
{
    private static final String YES = "Y";  
    private static final String NO = "N";  
    
    private Boolean valueOf(String value) throws SQLException
    {
        if (YES.equalsIgnoreCase(value))
            return new Boolean(true);
        else
            return new Boolean(false);
    }
 
    @Override
    public Boolean getResult(ResultSet resultSet, String name) throws SQLException
    {
        return valueOf(resultSet.getString(name));
    }

    @Override
    public Boolean getResult(CallableStatement statement, int position) throws SQLException
    {
        return valueOf(statement.getString(position));  
    }
 
    @Override
    public void setParameter(PreparedStatement statement, int position, Boolean value, JdbcType jdbcType) throws SQLException
    {
        statement.setString(position, value.booleanValue() ? YES : NO);  
    }

}

=========================
問題2: Insert語句中, 如何使用Oracle的sequence對象
摘自 http://javaeenotes.blogspot.com/2011/10/mybatis-and-oracle-database.html (通過bing 搜索引擎可以看到cache)
=========================
Unlike other databases like MySQL, the Oracle database does not provide the functionality to generate primary keys automatically when inserting rows.
    public interface ClientMapper {  
      @Insert("INSERT INTO client (id, name) VALUES (#{id}, #{name})")  
      @SelectKey(  
                keyProperty = "id",  
                before = true,  
                resultType = Integer.class,  
                statement = { "SELECT client_seq.nextval AS id FROM dual" })  
      public Integer insertClient(Client client);  
    }  
    
    
    
=========================
最后, 列出幾個不錯的參考文章
=========================
   mybatis3入門學習筆記 (五star推薦)
   http://blessht.iteye.com/blog/1097005   
   
   有關 sql xml 的寫法, 可以參考下面2個文章, 講的很清晰
   cms項目第9天(上)-mybatis框架
   http://blog.sina.com.cn/s/blog_6bcb0a8c0100q6ub.html
   cms項目第9天(下)-mybatis框架
   http://blog.sina.com.cn/s/blog_6bcb0a8c0100q6ud.html

   MyBatis+Spring基於接口編程的原理分析
   http://denger.iteye.com/blog/1060588
    
   MyBatis 緩存機制深度解剖 / 自定義二級緩存
   http://denger.iteye.com/blog/1126423
   
   使用Mybatis Generator自動生成Mybatis相關代碼
   http://qiuguo0205.iteye.com/blog/819100      
   
   log4jdbc 日志框架介紹, 因為mybatis基本上是使用preparedStatement, 所以打出的日志, sql和參數值是分開的, 可讀性不好, log4jdbc 可以解決這個問題.  
   http://badqiu.iteye.com/blog/743100
   http://indure.chinaunix.com/space.php?uid=78707&do=blog&id=1631151
   官網:http://code.google.com/p/log4jdbc/wiki/FAQ

   幾個個英文教程, 寫得還算可以吧.
   http://javaeenotes.blogspot.com/2011/10/mybatis-and-oracle-database.html (通過bing 搜索引擎可以看到cache)
   http://mybatis.co.uk/index.php/2010/09/mybatis-simple-and-complete-example.html
   http://blog.idleworx.com/2010/06/idleworxs-mybatis-tutorials.html
  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM