1. 程式人生 > >Mybatis入門以及配置檔案解析

Mybatis入門以及配置檔案解析

一 mybatis入門

1.1 mybatis是什麼
    MyBatis是一個簡化和實現了 Java 資料持久化層(persistence layer)的開源框架,它抽象了大量的JDBC冗餘程式碼,並提供了一個簡單易用的API和資料庫互動。
    MyBatis的前身是iBATIS,iBATIS於2002年由ClintonBegin建立。MyBatis3是iBATIS的全新設計,支援註解和Mapper。
    MyBatis流行的主要原因在於它的簡單性和易使用性。在Java應用程式中,資料持久化層涉及到的工作有:將從資料庫查詢到的資料生成所需要的Java物件;將Java物件中的資料通SQL持久化到資料庫中。
    MyBatis通過抽象底層的JDBC程式碼,自動化SQL結果集產生Java物件、Java物件的資料持久化資料庫中的過程使得對SQL的使用變得容易。

1.2 Git 是一個免費開源的分散式版本控制系統,被用於高速有效地處理大大小小專案中所有檔案,在軟體開發中使用的其他版本控制軟體類似與SVN、VSS、CVS等等.

1.3 作為一個分散式的版本控制系統,在Git中並不存在主庫這樣的概念,每一份複製出的庫都可以獨立使用,任何兩個庫之間的不一致之處都可以進行合併。github以託管各種git庫,並提供一個web介面,可以說是一款易於使用的git圖形客戶端。我們熟知的spring、struts、Hibernate等框架的原始碼在github上面都可以找到其原始碼

1.4 iBATIS一詞來源於internet和abatis的組合,是一個在2002年發起的開放原始碼專案。於2010年6月16號被谷歌託管,改名為MyBatis。
    ibatis的官網 http://ibatis.apache.org/ 進去官網會看到下面提示:
    apache ibatis is retired at the apache software foundation (2010/06/16)
    the original project team has moved to mybatis hosted at google code. see http://www.mybatis.org/ for more.
    然而http://www.mybatis.org/這個地址一直處於打不開狀態...
    但是我們最終是可以在github中找到mybatis的相關下載的:
    mybatis在github中的地址
    https://github.com/mybatis/mybatis-3
    最新版本的mybatis的下載地址
    https://github.com/mybatis/mybatis-3/releases
    doc文件
    http://www.mybatis.org/mybatis-3/

1.5 當前有很多Java實現的持久化框架,而MyBatis流行起來有以下原因:
    1.5.1 它消除了大量的JDBC冗餘程式碼
        Java通過JDBC的API來操作關係型資料庫,但是JDBC是一個非常底層的API,我們需要書寫大量的程式碼來完成對資料庫的操作。例如一個插入操作(參考之前學習JDBC時候的程式碼例項)
        但是使用mybatis來完成相同的插入操作要簡單方便靈活的多:
        第一步:在SQLMapper對映配置檔案中配置SQL語句,假定為StudentMapper.xml
        <insert id="insertStudent" parameterType="Student">
            INSERT INTO STUDENTS(ID,NAME,EMAIL) 
            VALUES(#{id},#{name},#{email})
        </insert>
        第二步:建立一個StudentMapper介面
        public interface StudentMapper{
            void insertStudent(Student student);
        }
        第三步:編寫java程式碼完成插入操作:
        SqlSession session = getSqlSessionFactory().openSession();
        StudentMapper mapper = session.getMapper(StudentMapper.class);
        mapper.insertStudent(student);

        特別之處的是,MyBatis還提供了其他的一些特性來簡化持久化邏輯的實現
        它支援複雜的SQL結果集資料對映到巢狀的物件結構
        它支援一對一和一對多的結果集和Java物件的對映
        它支援根據輸入的資料構建動態的SQL語句
    1.5.2 它有低的學習曲線
        MyBatis能夠流行的首要原因之一在於它學習和使用起來非常簡單,它取決於你Java和 SQL方面的知識。如果開發人員很熟悉Java和SQL,他們會發現MyBatis入門非常簡單。
    1.5.3 它能很好地與傳統資料庫協同工作
        有時我們可能需要用不正規形式與傳統資料庫協同工作,使用成熟的ORM框架(例如大家熟知的Hibernate)有可能、但是很難跟傳統資料庫很好地協同工作,因為他們嘗試將Java物件靜態地對映到資料庫的表上.而MyBatis是將查詢的結果與Java物件對映起來,這使得MyBatis可以很好地與傳統資料庫協同工作。你可以根據面相物件的模型建立Java域物件,執行傳統資料庫的查詢,然後將結果對映到對應的Java物件上。
    1.5.4 它可以接受SQL語句
        成熟的ORM框架鼓勵使用實體物件和在其底層自動產生SQL語句。由於這種的SQL生成方式,我們有可能不能夠利用到資料庫的一些特有的特性。Hibernate允許執行本地SQL,但是這樣會打破持久層和資料庫獨立的原則。MyBatis框架接受SQL語句,而不是將其對開發人員隱藏起來。由於MyBatis不會產生任何的SQL語句,所以開發人員就要準備SQL語句,這樣就可以充分利用資料庫特有的特性並且可以準備自定義的查詢。另外,MyBatis 對儲存過程也提供了支援。
    1.5.5 它提供了與Spring框架的整合支援
        MyBatis提供了與流行的依賴注入框架Spring的開包即用的整合支援,這將進一步簡化MyBatis的使用
    1.5.6 它提供了與第三方快取類庫的整合支援
        MyBatis有內建的SqlSession級別的快取機制,用於快取Select語句查詢出來的結果。除此之外,MyBatis提供了與多種第三方快取類庫的整合支援,如EHCache,OSCache,Hazelcast等。
    1.5.7 它引入了更好的效能
        效能問題是關乎軟體應用成功與否的關鍵因素之一。為了達到更好的效能,需要考慮很多事情,而對很多應用而言,資料持久化層是整個系統性能的關鍵。MyBatis支援資料庫連線池,消除了為每一個請求建立一個數據庫連線的開銷,MyBatis提供了內建的快取機制,在SqlSession級別提供了對SQL查詢結果的快取。即:如果你呼叫了相同的select查詢,MyBatis 會將放在快取的結果返回,而不會去再查詢資料庫。MyBatis框架並沒有大量地使用代理機制,因此對於其他的過度地使用代理的ORM框架而言,MyBatis可以獲得更好的效能.

1.6 mybatis的jar包
    mybatis的核心包只有一個mybatis-3.x.0.jar,另外還有一些【可選】的依賴包(日誌、代理等所需要的),在下載的壓縮包中可以找到.

1.7 mybatis框架中一般需要倆種檔案:
    第一種:mybatis的配置檔案: mybatis-config.xml,其中包括資料庫連線資訊,類型別名等等
        特點:
            名字一般是固定的
            位置是src下面
        示例:
        <?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="Student" type="com.ijavac.pojo.Student" />
          </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/test" />
                -->
                <property name="driver" value="oracle.jdbc.driver.OracleDriver" />
                <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:XE" />
                <property name="username" value="test" />
                <property name="password" value="test" />
              </dataSource>
            </environment>
          </environments>
          <mappers>
            <mapper resource="com/ijavac/pojo/StudentMapper.xml" />
          </mappers>
        </configuration>


    第二種:mybatis的對映檔案:XxxxxMapper.xml,這個xml檔案中包括Xxxx類所對應的資料庫表的各種增刪改查sql語句
        特點:
            名字一般為XxxxMapper.xml,Xxxx是對應類的名字
            位置不固定,一般放到一個專門的package裡面
        例項:
        <?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.ijavac.pojo.StudentMapper">
          <resultMap type="Student" id="StudentResult">
            <id property="id" column="id" />
            <result property="name" column="name" />
            <result property="email" column="email" />
          </resultMap>
          <select id="findAllStudents" resultMap="StudentResult">
                SELECT * FROM STUDENTS
          </select>
          <select id="findStudentById" parameterType="int" resultType="Student">
             SELECT ID AS STUDID, NAME, EMAIL 
                 FROM STUDENTS WHERE ID=#{Id}
          </select>
          <insert id="insertStudent" parameterType="Student">
             INSERT INTO STUDENTS(ID,NAME,EMAIL) 
                 VALUES(#{id },#{name},#{email})
          </insert>
        </mapper>

1.8 mybatis中的對映介面XxxxMapper.java(對XxxxMapper.xml中的sql語句進行對映)
    mybatis中除了必須的jar包、各種xml配置檔案之外,一般還需要有呼叫sql語句執行的介面XxxxMapper.java
    示例:
    public interface StudentMapper{
        List<Student> findAllStudents();
        Student findStudentById(Integer id);
        void insertStudent(Student student);
    }
    注意:介面中的方法的名字和XML檔案定義的SQL對映語句的名稱要相同
    同時我們不需要去實現該介面,因為mybatis中提供了相應的方式在執行期間動態生成該介面的實現類物件(動態代理技術,spring框架中會詳細講解動態代理).

1.9 mybatis中的SqlSession介面和sqlSessionFactory介面
    SqlSession介面的實現類物件是mybatis中最重要的一個物件,我們可以使用該物件動態獲得XxxxMapper.java介面的實現類物件,然後就可以呼叫到XxxxMapper.java介面中方法所對映的sql語句(在xml檔案中配置的sql語句)。
    sqlSessionFactory介面的實現類物件是一個工廠物件,專門負責來產生SqlSession物件的
    例如:
    InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    SqlSession sqlSession = sqlSessionFactory.openSession();

    //第一種執行sql語句的方式  通過XxxxMapper介面的實現類物件來呼叫
    //動態獲得XxxxMapper介面的實現類
    StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
    studentMapper.insertStudent(new Student(1,"tom","
[email protected]
")); //第二種執行sql語句的方式 執行呼叫XxxxMapper.xml中寫好的sql語句 //也可以【不通過】Mapper介面執行對映的SQL //然而,使用 Mapper介面是最佳實踐 //sqlSession.selectOne("com.ijavac.pojo.StudentMapper.findStudentById",1); 1.10 編寫一個簡單的mybatis進行插入資料的例項 1.10.1 資料庫建表 dob=Date of Birth CREATE TABLE STUDENTS ( stu_id number PRIMARY KEY, name varchar2(50) , email varchar2(50) , dob date ); 1.10.2 新建一個專案,建立好相應的package及class package com.ijavac.pojo; import java.util.Date; public class Student { private Integer studId; private String name; private String email; private Date dob; get/set } 1.10.3 專案中引入mybatis的核心包以及可選的依賴包 必須的包 mybatis-3.3.0.jar ojdbc14.jar 可選的包 junit-4.7.jar log4j-1.2.17.jar 1.10.4 mybatis中的配置檔案和對映檔案分別引入到專案中 src下面的mybatis-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 type="com.ijavac.pojo.Student" alias="Student" /> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="oracle.jdbc.driver.OracleDriver" /> <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:XE" /> <property name="username" value="test" /> <property name="password" value="test" /> </dataSource> </environment> </environments> <mappers> <mapper resource="com/ijavac/mappers/StudentMapper.xml"/> </mappers> </configuration> com.ijavac.mappers包下面的StudentMapper.xml: <?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"> <!-- com.ijavac.mappers.StudentMapper是我們定義介面的全限定名字 這樣就可以使用介面呼叫對映的SQL語句了 這個名字一定要和介面對應上--> <mapper namespace="com.ijavac.mappers.StudentMapper"> //和定義的介面路徑一致 <resultMap type="Student" id="StudentResult"> <id property="studId" column="stud_id" /> <result property="name" column="name" /> <result property="email" column="email" /> <result property="dob" column="dob" /> </resultMap> <select id="findAllStudents" resultMap="StudentResult"> SELECT * FROM STUDENTS </select> <!-- 列名和屬性名字不一致可以給查詢的列起一個別名 --> <select id="findStudentById" parameterType="int" resultType="Student"> SELECT STUD_ID AS STUDID,NAME,EMAIL,DOB FROM STUDENTS WHERE STUD_ID=#{id} </select> <insert id="insertStudent" parameterType="Student"> INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,DOB) VALUES(#{studId},#{name},#{email},#{dob}) </insert> </mapper> 1.10.5 配置log4j.properties檔案中的日誌輸出: 位置src下面 內容: log4j.rootLogger=DEBUG, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d [%-5p] %c - %m%n #show sql log4j.logger.java.sql.ResultSet=INFO log4j.logger.org.apache=INFO log4j.logger.java.sql.Connection=DEBUG log4j.logger.java.sql.Statement=DEBUG log4j.logger.java.sql.PreparedStatement=DEBUG 1.10.6 com.ijavac.mappers包下面新建一個介面StudentMapper.java,用來對應xml檔案中的sql語句(對映),從而方便我們呼叫 package com.ijavac.mappers; import java.util.List; import com.ijavac.pojo.Student; //建立對映器Mapper介面StudentMapper //方法名和StudentMapper.xml中定義的SQL對映定義名相同 //這個其實就是dao層介面(資料訪問層,負責和資料庫進行互動) public interface StudentMapper { List<Student> findAllStudents(); Student findStudentById(Integer id); void insertStudent(Student student); } 1.10.7 建立一個測試類StudentMapperTest.java package test; import java.io.InputStream; import java.util.Date; 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 org.junit.Test; import com.ijavac.mappers.StudentMapper; import com.ijavac.pojo.Student; public class StudentMapperTest { @Test public void testInsert(){ try { InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class); Student s = new Student(1,"tom","
[email protected]
",new Date()); studentMapper.insertStudent(s); sqlSession.commit(); } catch (Exception e) { e.printStackTrace(); } } } 1.10.8 執行成功後會在控制檯中看到log4j日誌輸出的這個程式執行的相關資訊 1.10.9 對mybatis的一些基本封裝 每次讀取配置檔案,產生一個工廠物件SqlSessionFactory,然後再生成出SqlSession物件,這個過程雖然並不複雜,但是也都是一些重複的程式碼流程,所以我們可以對其進行一個簡單的封裝: package com.ijavac.utils; import java.io.IOException; import java.io.InputStream; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class MyBatisSqlSessionFactory { private static SqlSessionFactory sqlSessionFactory; public static SqlSessionFactory getSqlSessionFactory(){ if(sqlSessionFactory == null){ InputStream inputStream = null; try { inputStream = Resources.getResourceAsStream("mybatis-config.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e.getCause()); } } return sqlSessionFactory; } public static SqlSession openSession() { return getSqlSessionFactory(). openSession(false); } public static SqlSession openSession(boolean autoCommit) { return getSqlSessionFactory().openSession(autoCommit); } } 之後每次使用的時候只需要呼叫該類中的靜態方法openSession即可 上面的程式碼可簡寫為: //注意事務是自動提交還是手動提交 MyBatisSqlSessionFactory.openSession().getMapper(StudentMapper.class).insertStudent(s);

二 mybatis配置詳解

MyBatis最關鍵的組成部分是SqlSessionFactory,我們可以從中獲取SqlSession, 並執行對映的SQL語句。SqlSessionFactory物件可以通過基於XML的配置資訊或者JavaAPI建立。

2.1 使用xml配置Mybatis
    構建SqlSessionFactory最常見的方式是基於XML配置。下面的 mybatis-config.xml展示了一個典型的MyBatis配置檔案的樣子:
    <?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>
      <properties resource="application.properties">
        <property name="username" value="db_user" />
        <property name="password" value="verysecurepwd" />
      </properties>
      <settings>
        <setting name="cacheEnabled" value="true" />
      </settings>
      <typeAliases>
        <typeAlias alias="Student" type="com.ijavac.pojo.Student" />
        <package name="com.ijavac.pojo" />
      </typeAliases>
      <typeHandlers>
        <typeHandler handler="com.mybatis3.typehandlers.PhoneTypeHandler" />
        <package name="com.ijavac.typehandlers" />
      </typeHandlers>
      <environments default="development">
        <environment id="development">
          <transactionManager type="JDBC" />
          <dataSource type="POOLED">
            <property name="driver" value="${jdbc.driverClassName}" />
            <property name="url" value="${jdbc.url}" />
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
          </dataSource>
        </environment>
        <environment id="production">
          <transactionManager type="MANAGED" />
          <dataSource type="JNDI">
            <property name="data_source" value="java:comp/jdbc/MyBatisDemoDS" />
          </dataSource>
        </environment>
      </environments>
      <mappers>
        <mapper resource="com/ijavac/mappers/StudentMapper.xml" />
        <mapper url="file:///D:/mybatisdemo/mappers/StudentMapper.xml" />
        <mapper class="com.ijavac.mappers.StudentMapper" />
      </mappers>
    </configuration>

    2.1.1 environments元素
    environments是配置mybatis當前工作的資料庫環境的地方
    MyBatis支援配置多個dataSource環境,可以將應用部署到不同的環境上,如DEV(開發環境),TEST(測試環境),QA(質量評估環境),UAT(使用者驗收環境),PRODUCTION(生產環境),可以通過將預設environments值設定成想要的environment的id值。

    有時候,我們可能需要在相同的應用下使用多個數據庫,比如我們可能有shoppingcart資料庫來儲存所有的訂單明細;使用reports資料庫儲存訂單明細的合計,用作報告。(也就是如果系統在執行期間如果有切換資料庫環境的需求,mybatis中也可以很輕鬆的實現).
    如果你的應用需要連線多個數據庫,你需要將每個資料庫配置成獨立的環境,並且為每一個數據庫建立一個SqlSessionFactory
    例如:
    <environments default="shoppingcart">
      <environment id="shoppingcart">
        <transactionManager type="MANAGED" />
        <dataSource type="JNDI">
          <property name="data_source" value="java:comp/jdbc/ShoppingcartDS" />
        </dataSource>
      </environment>
      <environment id="reports">
        <transaction Managertype="MANAGED" />
        <dataSource type="JNDI">
          <property name="data_source" value="java:comp/jdbc/ReportsDS" />
        </dataSource>
      </environment>
    </environments>

    我們可以為以上每個環境建立一個SqlSessionFactory
    java程式碼:
    inputStream = Resources.getResourceAsStream("mybatis-config.xml");
    //預設的環境
    defaultSqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

    //統計明細的環境
    cartSqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, "shoppingcart");

    //統計報表的環境
    reportSqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, "reports");

    注意:對於environments,我們可以在其中配置多個environment子元素,同時還需要在environment中配置dataSource和transactionManager元素。


    2.1.2 dataSource元素
    dataSource表示的是資料來源:至少會包括該連線資料庫的各種資訊
    <dataSource type="POOLED">
      <property name="driver" value="${jdbc.driverClassName}" />
      <property name="url" value="${jdbc.url}" />
      <property name="username" value="${jdbc.username}" />
      <property name="password" value="${jdbc.password}" />
    </dataSource>

    dataSource的型別type屬性可以配置成其內建型別之一,如UNPOOLED,POOLED,JNDI。
    如果將型別設定成UNPOOLED,MyBatis會為每一個數據庫操作建立一個新的連線,使用完了並關閉它,該方式適用於只有小規模數量併發使用者的簡單應用程式上。

    如果將屬性設定成POOLED,MyBatis會建立一個數據庫連線池,連線池中的一個連線將會被用作資料庫操作。一旦資料庫操作完成,MyBatis會將此連線返回給連線池。在開發或測試環境中,經常使用此種方式。
 
    如果將型別設定成JNDI(Java Naming and Directory Interface , Java命名和目錄介面, 是SUN公司提供的一種標準的Java命名系統介面),MyBatis從在應用伺服器向配置好的JNDI資料來源dataSource獲取資料庫連線。在生產環境中,優先考慮這種方式。


    2.1.3 transactionManager元素 :事務管理器
    MyBatis支援兩種型別的事務管理器:JDBC 和 MANAGED.
    JDBC事務管理器的使用,是在【jdbc程式】負責管理資料庫連線的生命週期(提交、回退等等)的時候。如果將TransactionManager 屬性設定成JDBC,MyBatis內部將使用JdbcTransactionFactory類建立TransactionManager。例如,部署到ApacheTomcat的應用程式,需要應用程式自己管理事務。
    MANAGED 事務管理器的使用,是在【應用伺服器】負責管理資料庫連線生命週期的時候。如果將TransactionManager屬性設定成MANAGED時,MyBatis內部使用ManagedTransactionFactory 類建立事務管理器TransactionManager。例如,當一個Java EE的應用程式部署在類似JBoss,WebLogic,GlassFish應用伺服器上時,它們會使用EJB進行應用伺服器的事務管理能力。在這些管理環境中,你可以使用MANAGED事務管理器。
    注:Managed 是託管的意思,即我們編寫的應用程式本身不去管理事務,而是把事務管理交給應用所在的伺服器進行管理。

    2.1.4 properties元素
    屬性配置元素properties可以將配置值寫死到mybatis-config.xml中,也可以具體到一個屬性檔案中,並且使用屬性檔案的key名作為佔位符.
    在上述的配置中,我們將資料庫連線屬性配置到了application.properties檔案中,並且為driver,URL等屬性使用了佔位符.

    在applications.properties檔案中配置資料庫連線引數,如下所示:
    jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
    jdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:XE
    jdbc.username=test
    jdbc.password=test

    在mybatis-config.xml檔案中,為屬性使用application.properties檔案中定義的佔位符:
    <!-- 讀取application.properties檔案中的資料key-value的形式 -->
    <properties resource="application.properties">
      <!-- 注意:是applications.properties檔案中的值優先順序高 -->
      <property name="jdbc.username" value="ijavac" />
      <property name="jdbc.password" value="ijavac" />
    </properties>
    <environments default="development">
        <environment id="development">
          <transactionManager type="JDBC" />
          <dataSource type="POOLED">
            <property name="driver" value="${jdbc.driverClassName}" />
            <property name="url" value="${jdbc.url}" />
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
          </dataSource>
        </environment>
    </environments> 


    2.1.5 typeAliases元素: 類型別名
    在SQLMapper配置檔案中,對於resultType和parameterType屬性值,我們需要使用JavaBean 的完全限定名。
    例如:
    <select id="findStudentById" parameterType="int" 
        resultType="com.ijavac.pojo.Student">
            SELECT STUD_ID AS ID, NAME, EMAIL, DOB 
            FROM STUDENTS WHERE STUD_ID=#{Id}
    </select>
    <update id="updateStudent" parameterType="com.ijavac.pojo.Student">
        UPDATE STUDENTS 
            SET NAME=#{name}, EMAIL=#{email}, DOB=#{dob} 
            WHERE STUD_ID=#{id}
    </update>

    注:parameterType表示將來呼叫這個sql語句的時候所傳的引數的型別(引數值或者引數物件裡面的屬性值 用來替換sql語句中的佔位符)
    resultType表示將來呼叫這個sql語句的時候所返回的結果的型別(方便mybatis給我們自動封裝結果集)

    這裡我們為resultType和parameterType屬性值設定為Student型別的完全限定名:com.ijavac.com.Student

    我們可以為完全限定名取一個別名(alias),然後就可以在需要使用完全限定名的地方使用別名,而不是到處使用完全限定名。如下例子所示,為完全限定名起一個別名:
    <type Aliases>
      <type Alias alias="Student" type="com.ijavac.pojo.Student" />
      <type Alias alias="Teacher" type="com.ijavac.pojo.Teacher" />
    </type Aliases>

    然後在SQLMapper對映檔案中, 如下使用Student的別名:
    <select id="findStudentById" parameterType="int" resultType="Student">
        SELECT STUD_ID AS ID, NAME, EMAIL, DOB 
        FROM STUDENTS WHERE STUD_ID=#{id}
    </select>
    <update id="updateStudent" parameterType="Student">
        UPDATE STUDENTS 
            SET NAME=#{name}, EMAIL=#{email}, DOB=#{dob} 
        WHERE STUD_ID=#{id}
    </update>

    你可以不用為每一個JavaBean單獨定義別名,你可以為配置出需要取別名的類的所在的包(package),MyBatis會自動掃描包內定義的類,然後分別為每個類註冊一個小寫字母開頭的簡單類名形式的別名。如下所示:
    <type Aliases>
      <package name="com.ijavac.pojo" />
    </type Aliases>
    如果Student.java和 Teacher.java 定義在com.ijavac.pojo包中,則 com.ijavac.pojo.Student的別名會被註冊為student。而com.ijavac.pojo.Teacher別名將會被註冊為teacher

    還有另外一種方式為JavaBeans起別名,使用註解 @Alias:
    @Alias("stu")
    public class Student{
        ....
    }
    @Alias註解將會覆蓋配置檔案中的<typeAliases>定義。



    2.1.6 typeHandlers元素: 型別處理器
    當MyBatis將一個Java物件作為輸入引數執行INSERT語句操作時,它會建立一個PreparedStatement物件,並且使用setXXX()方法對佔位符設定相應的引數值 。這裡,XXX可以是Int,String,Date 等 Java物件屬性型別的任意一個。示例如下:
    <insert id="insert Student" parameter Type="Student">
        INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,DOB) 
        VALUES(#{stud Id},#{name},#{email},#{dob})
    </insert>

    為執行這個語句,MyBatis將採取以下一系列動作:
        建立一個有佔位符的PreparedStatement介面,如下:
        Prepared Statement ps = connection.prepare Statement
                ("INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,DOB) VALUES(?,?,?,?)");
        檢查Student物件的屬性studId的型別,然後使用合適setXXX方法去設定引數值。這裡studId是integer型別,所以會使用setInt()方法:ps.setInt(1,student.getStudId());

        類似地,對於name和email屬性都是String型別MyBatis使用setString()方法設定引數。
        至於dob屬性, MyBatis會使用setDate()方法設定dob處佔位符位置的值。
        MyBaits會將java.util.Date型別轉換為java.sql.Timestamp並設值:
        ps.setTimestamp(4, new Timestamp((student.getDob()).getTime()));

    但MyBatis是怎麼知道對於Integer型別屬性使用setInt()和String型別屬性使用setString()方法呢?其實MyBatis是通過使用型別處理器typeHandlers來決定這麼做的。

    MyBatis對於以下的型別使用內建的型別處理器:所有的基本資料型別、基本型別的包裹型別、 byte[]、java.util.Date、java.sql.Date、java,sql.Time、java.sql.Timestamp、java列舉型別等。所以當MyBatis發現屬性的型別屬於上述型別,他會使用對應的型別處理器將值設定到PreparedStatement中,同樣地,當SQL結果集封裝成java類物件的時候,也有類似的過程。

    那如果有一個自定義的型別,怎麼儲存儲存到資料庫呢?示例如下:假設表STUDENTS 有一個 PHONE 欄位,型別為 VARCHAR2(15),而 Student類有一個自定義型別屬性
    alter table students add phone varchar2(15);
    alter table students drop column phone;

    java程式碼:
    PhoneNumber 類定義型別的 phoneNumber 屬性。

    public class PhoneNumber{
        private String countryCode;
        private String stateCode;
        private String number;
        public PhoneNumber(){
        }
        public PhoneNumber(String countryCode, String stateCode, String number) {
            this.countryCode = countryCode;
            this.stateCode = stateCode;
            this.number = number;
        }
        public String getAsString() {
            return countryCode + "-" + stateCode + "-" + number;
        }
        // Setters and getters
    }

    public class Student{
        private Integer id;
        private String name;
        private String email;
        private PhoneNumber phone;
        // Setters and getters
    }


    xml配置:
    <insert id="insertStudent" parameter Type="Student">
        insert into students(name,email,phone)
        values(#{name},#{email},#{phone})
    </insert>

    這裡,引數物件中的屬性phone的值需要傳遞給#{phone};而引數物件的屬性phone是 PhoneNumber型別。但是,MyBatis 並不知道該怎樣來處理這個型別的物件。
    為了讓MyBatis明白怎樣處理這個自定義的Java物件型別,如PhoneNumber,我們可以建立一個自定義的型別處理器,MyBatis提供了抽象類BaseTypeHandler<T> ,我們可以繼承此類建立自定義型別處理器。
    程式碼如下所示:
        package com.ijavac.typehandlers;

        import java.sql.CallableStatement;
        import java.sql.PreparedStatement;
        import java.sql.ResultSet;
        import java.sql.SQLException;

        import org.apache.ibatis.type.BaseTypeHandler;
        import org.apache.ibatis.type.JdbcType;

        import com.ijavac.pojo.PhoneNumber;

        public class PhoneTypeHandler extends BaseTypeHandler<PhoneNumber>{

            //遇到PhoneNumber引數的時候應該如何在ps中設定值
            @Override
            public void setNonNullParameter(PreparedStatement ps, int i, PhoneNumber parameter, JdbcType jdbcType)
                    throws SQLException {
                ps.setString(i, parameter.getAsString());
            }

            //查詢中遇到PhoneNumber型別的應該如何封裝(使用列名封裝)
            @Override
            public PhoneNumber getNullableResult(ResultSet rs, String columnName) throws SQLException {
                return new PhoneNumber(rs.getString(columnName));
            }

            //查詢中遇到PhoneNumber型別的應該如何封裝(使用列的下標)
            @Override
            public PhoneNumber getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
                return new PhoneNumber(rs.getString(columnIndex));
            }

            //CallableStatement使用中遇到了PhoneNumber型別的應該如何封裝
            @Override
            public PhoneNumber getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
                return new PhoneNumber(cs.getString(columnIndex));
            }

        }

    注意:使用ps.setString()和rs.getString()方法是 :因為在資料庫的表中phone列是VARCHAR型別。

    最後一旦我們實現了自定義的型別處理器,我們需要在mybatis-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>
      <properties resource="application.properties" />
      <type Handlers>
        <type Handler handler="com.ijavac.typehandlers.PhoneTypeHandler" />
      </type Handlers>
    </configuration>
    註冊PhoneTypeHandler後, MyBatis就能夠將Phone型別的物件值儲存到VARCHAR型別的列上。



    2.1.7 settings元素: 全域性引數設定
    注意:大多數情況下,【這些引數使用它們的預設值即可】
    為滿足應用特定的需求,MyBatis預設的全域性引數設定可以被覆蓋掉,如下所示:
    <settings>
      <setting name="cacheEnabled" value="true" />
      <setting name="lazyLoadingEnabled" value="true" />
      <setting name="multipleResultSetsEnabled" value="true" />
      <setting name="useColumnLabel" value="true" />
      <setting name="useGeneratedKeys" value="false" />
      <setting name="autoMappingBehavior" value="PARTIAL" />
      <setting name="defaultExecutorType" value="SIMPLE" />
      <setting name="defaultStatementTimeout" value="25000" />
      <setting name="safeRowBoundsEnabled" value="false" />
      <setting name="mapUnderscoreToCamelCase" value="false" />
      <setting name="localCacheScope" value="SESSION" />
      <setting name="jdbcTypeForNull" value="OTHER" />
      <setting name="lazyLoadTriggerMethods" value="equals,clone,hash Code ,to String" />
      <setting name="proxyFactory" value="JAVASSIST" />
      <setting name="aggressiveLazyLoading" value="true" />
      <setting name="logImpl" value="LOG4J " />
      <setting name="logPrefix" value="LOG4J " />
      <setting name="callSettersOnNulls" value="false " />
    </settings>


    <settings>
      <!-- 這個配置使全域性的對映器啟用或禁用快取 -->
      <setting name="cacheEnabled" value="true" />

      <!-- 全域性啟用或禁用延遲載入。當禁用時,所有關聯物件都會即時載入 -->
      <setting name="lazyLoadingEnabled" value="true" />

      <!-- 允許或不允許多種結果集從一個單獨的語句中返回(需要適合的驅動) -->
      <setting name="multipleResultSetsEnabled" value="true" />

      <!-- 使用列標籤代替列名。不同的驅動在這方便表現不同。參考驅動文件或充分測試兩種方法來決定所使用的驅動 -->
      <setting name="useColumnLabel" value="true" />

      <!-- 允許JDBC支援生成的鍵。需要適合的驅動。 -->
      <setting name="useGeneratedKeys" value="false" />

      <!-- 指定MyBatis如何自動對映列到欄位/屬性。PARTIAL只會自動對映簡單、沒有巢狀的結果。FULL會自動對映任意複雜的結果(巢狀的或其他情況) -->
      <setting name="autoMappingBehavior" value="PARTIAL" />

      <!-- 配置預設的執行器。SIMPLE執行器沒有什麼特別之處。REUSE執行器重用預處理語句。BATCH執行器重用語句和批量更新 -->
      <setting name="defaultExecutorType" value="SIMPLE" />

      !-- 設定超時時間,它決定驅動等待一個數據庫響應的時間 -->
      <setting name="defaultStatementTimeout" value="25000" />

      <!-- 允許在巢狀語句中使用分頁(RowBounds)預設false -->
      <setting name="safeRowBoundsEnabled" value="false" />

      <!-- 是否開啟自動駝峰命名規則(camel case)對映,即從經典資料庫列名 A_COLUMN 到經典 Java 屬性名 aColumn 的類似對映。預設false -->
      <setting name="mapUnderscoreToCamelCase" value="false" />

      <!-- MyBatis 利用本地快取機制(Local Cache)防止迴圈引用(circular references)和加速重複巢狀查詢。 預設值為 SESSION,這種情況下會快取一個會話中執行的所有查詢。 若設定值為 STATEMENT,本地會話僅用在語句執行上,對相同 SqlSession 的不同調用將不會共享資料。 -->
      <setting name="localCacheScope" value="SESSION" />

      <!-- 當沒有為引數提供特定的 JDBC 型別時,為空值指定 JDBC 型別。 某些驅動需要指定列的 JDBC 型別,多數情況直接用一般型別即可,比如 NULL、VARCHAR 或 OTHER。 -->
      <setting name="jdbcTypeForNull" value="OTHER" />

      <!-- 指定物件的哪個方法觸發一次延遲載入。 -->
      <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode ,toString" />

      <!-- CGLIB | JAVASSIST 預設JAVASSIST(MyBatis 3.3 or above)  -->
      <!-- 指定 Mybatis 建立具有延遲載入能力的物件所用到的代理工具。 -->
      <setting name="proxyFactory" value="JAVASSIST" />
      <!-- 當啟用時,對任意延遲屬性的呼叫會使帶有延遲載入屬性的物件完整載入;反之,每種屬性將會按需載入。 -->
      <setting name="aggressiveLazyLoading" value="true" />

      <!-- 指定 MyBatis 所用日誌的具體實現,未指定時將自動查詢。 -->
      <setting name="logImpl" value="LOG4J " />

      <!-- 指定 MyBatis 增加到日誌名稱的字首。值可以是任意字串 -->
      <setting name="logPrefix" value="LOG4J " />

      <!-- 指定當結果集中值為 null 的時候是否呼叫對映物件的 setter(map 物件時為 put)方法,這對於有 Map.keySet() 依賴或 null 值初始化的時候是有用的。注意基本型別(int、boolean等)是不能設定成 null 的。 預設false-->
      <setting name="callSettersOnNulls" value="false " />
    </settings>



    2.1.8 mappers元素: SQL對映
    SQLMapper檔案中包含的SQL對映語句將會被應用通過使用其標籤中的id值來執行。我們需要在mybatis-config.xml檔案中配置SQLMapper檔案的位置。
    <mappers>
      <mapper resource="com/ijavac/mappers/StudentMapper.xml" />
      <mapper url="file:///D:/mybatisdemo/app/mappers/StudentMapper.xml" />
      <mapper class="com.ijavac.mappers.StudentMapper" />
      <package name="com.ijavac.mappers" />
    </mappers>

    以上每一個<mapper> 標籤都可以從不同型別的資源中載入對映mapper:
    resource屬性用來指定在classpath中的mapper檔案。
    url屬性用來通過完全檔案系統路徑或者web URL地址來指向mapper檔案
    class屬性用來指向一個mapper介面
    package屬性用來指向可以找到Mapper介面的包名


2.2 使用Java API配置MyBatis (屬於瞭解的內容,因為有了靈活的配置配置方法,這個方式幾乎不用)
    MyBatis的SqlSessionFactory介面除了使用基於XML的配置建立外也可以通過JavaAPI程式設計式地被建立。每在XML中配置的元素,都可以程式設計式的建立。
    因為mybatis框架讀取了我們配置的mybatis-config.xml中配置資訊之後,然後利用這些資訊去執行程式碼創建出我們需要的SqlSessionFactory,再從而進一步得到sqlSession,最後再進行各種資料庫操作。
    所以其實我們完全可以不去配置任何資訊直接把資訊寫在程式碼中,然後在按著之前的順序創建出我們需要的SqlSessionFactory,再從而進一步得到sqlSession,最後再進行各種資料庫操作。只是這樣做再大多數時候都會降低程式碼的靈活性,所以我們基本上接觸的框架都是有相應的配置檔案的.

    例如:使用Java API建立SqlSessionFactory物件,之前是讀取配置檔案之後再建立,現在是自己把資訊寫到程式碼中,然後再建立該物件
    public static SqlSessionFactory getSqlSessionFactory() {
        SqlSessionFactory sqlSessionFactory = null;
        try {
            DataSourcedata Source = DataSourceFactory.getDataSource();
            TransactionFactory transactionFactory = new JdbcTransactionFactory();
            Environment environment = new Environment("development", transactionFactory, dataSource);
            Configuration configuration = new Configuration(environment);
            configuration.getTypeAliasRegistry().registerAlias("student",Student.class);
            configuration.getTypeHandlerRegistry().register(PhoneNumber.class, PhoneTypeHandler.class);
            configuration.addMapper(StudentMapper.class);
            sqlSessionFactory = new SqlSessionFactoryBuilder().
            build(configuration);
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
        return sqlSessionFactory;
    }

    類似的,每個在XML中配置的元素,都可以程式設計式的建立.
    注:這裡就不一一介紹了,因為絕大多數情況下我們還是不會把配置資訊直接寫到程式碼中的

2.3 自定義MyBatis日誌
MyBatis使用其內部LoggerFactory作為真正的日誌類庫使用的門面。其內部的LaggerFactory會將日誌記錄任務委託給如下的所示某一個日誌實現,日誌記錄優先順序由上到下順序遞減:
 jar 包  加 配置檔案  

SLF4J
Apache Commons Logging
Log4j2
Log4j
JDK logging

如果MyBatis未發現上述日誌記錄實現,則MyBatis的日誌記錄功能無效,如果你的執行環境中,在classpath中有多個可用的日誌類庫,並且你希望MyBaits使用某個特定的日誌實現,你可以通過呼叫以下其中一個方法:
org.apache.ibatis.logging.LogFactory.useSlf4jLogging();
org.apache.ibatis.logging.LogFactory.useLog4JLogging();
org.apache.ibatis.logging.LogFactory.useLog4J2Logging();
org.apache.ibatis.logging.LogFactory.useJdkLogging();
org.apache.ibatis.logging.LogFactory.useCommonsLogging();
org.apache.ibatis.logging.LogFactory.useStdOutLogging();

注:
如果你想自定義MyBatis日誌記錄,你應該在呼叫任何其它方法之前呼叫以上的其中一個方法

相關推薦

Mybatis入門以及配置檔案解析

一 mybatis入門 1.1 mybatis是什麼 MyBatis是一個簡化和實現了 Java 資料持久化層(persistence layer)的開源框架,它抽象了大量的JDBC冗餘程式碼,並提供了一個簡單易用的API和資料庫互動。

mybatis——config全域性配置檔案解析

原文:https://www.cnblogs.com/pjfmeng/p/7677773.html 在全集配置檔案中引入dtd約束“http://mybatis.org/dtd/mybatis-3-config.dtd”,主要有以下幾個標籤,現在詳細解釋下這幾個標籤的使用 1、prop

nginx1-dns域名解析|nginx入門|win下搭建|配置檔案解析

DNS域名解析器 DNS,域名系統,是網際網路上作為域名和IP地址相互對映的一個分散式資料庫 目的:將域名轉化成ip 過程 ------------------本機------------------ 1.輸入網址(www.163.com) 2.瀏覽器檢查快取中有沒有這個域名

JavaEE-SSM:007 Mybatis配置檔案解析(4)

1.系統級別的typeHandler   2.自定義typeHandler   想要自己實現typeHandler,需要實現TypeHandler<T>介面,T就是你要轉換的Java型別 setParameter(PreparedSta

JavaEE-SSM:006 Mybatis配置檔案解析(3)

別名主要用於Mapper的xml檔案指定輸入型別或者返回結果型別的名稱的時候,替代全限定名。(前文已經提及如何使用別名)   1.系統級別的typeAlias(類型別名)     2.自定義別名   這裡的alias屬性值得是

JavaEE-SSM:005 Mybatis配置檔案解析(2)

setting配置不常用,給出配置說明:     本文給出Setting配置的全量程式碼:   <settings> <setting name="cacheEnabled" value="true"

JavaEE-SSM:004 Mybatis配置檔案解析(1)

1.配置項:不可顛倒順序     2.Properties配置   好處就是:一處配置,多處使用。當然不嫌麻煩,直接配置,不使用property也是可以的。 在Properties下配置相關的配置Property:name是引用的時候的名稱

JavaEE-SSM:009 Mybatis配置檔案解析(6)

檔案型別轉換器(不常用)   假設資料庫有blob格式的欄位儲存需求: 對應著POJO的byte陣列: ResultMap中有對應的typeHandler配置:   當然,我們可以在POJO中使用InputStream替代byte陣列,但

JavaEE-SSM:008 Mybatis配置檔案解析(5)

1.系統級列舉typeHandler--EnumOridinalTypeHAndler 資料庫儲存為數字 //建立一個列舉 public enum SexEnum { MALE(1,"男"), FEMALE(0,"女"); private int id;

ehcache配置檔案解析以及記憶體結構

<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation=

Mybatis配置檔案解析過程詳解

記錄是一種精神,是加深理解最好的方式之一。 這篇文章能夠幫你 學會如何對Mybatis進行有效配置,理解對應的配置含義,知其然知其所以然。 學會在Mybatis預設實現無法滿足需求的時候怎麼去擴充套件。 從構建SqlSessionFactory說起        

mybatis-Config.xml全域性配置檔案解析

一:mybatis-Config.xml配置檔案的內容和配置順序如下 properties(屬性)settings(全域性配置引數)typeAiases(類型別名)typeHandlers(型別處理器)objectFactory(物件工廠)plugins(外掛)enviro

mybatis框架搭建環境以及配置檔案

專案檔案位置(暫時這樣放實際開發不是這樣的) Configuration.xml  檔案mybatis配置 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//

Spring+SpringMVC+MyBatis深入學習及搭建(三)——MyBatis全域性配置檔案解析

MyBatis的全域性配置檔案SqlMapConfig.xml,配置內容和順序如下: properties(屬性) setting(全域性配置引數) typeAliases(類名別名) typeHandlers(類名處理器) objectFactory(物件工廠) plugins(外掛) environm

MyBatis簡單例項及配置檔案解析

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/

mybatis generator 配置檔案解析

這是mybatis3 generator 配置檔案,包括了主要的配置引數,具體的配置說明請在文章結尾處下載 完整的配置應用。  應用是基於myeclipse的java應用。  文章中的MBG指的就是MybatisGenerator這個工具。  <?xml version="1.0" encoding=

MyBatis配置檔案解析

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/

mybatis配置檔案解析

技術實現夢想--在mybatis中的mybaits-config.xml中的配置項檢視配置檔案中的連線 :http://mybatis.org/dtd/mybatis-3-config.dtd 便可清楚mybatis中屬性的書寫順序<!ELEMENTconfigurat

MyBatis 全域性配置檔案解析

### 1. dtd約束 1.config <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.or

mybatis原始碼配置檔案解析之一:解析properties標籤

mybatis作為日常開發的常用ORM框架,在開發中起著很重要的作用,瞭解其原始碼對日常的開發有很大的幫助。原始碼版本為:3-3.4.x,可執行到github進行下載。 從這篇文章開始逐一分析mybatis的核心配置檔案(mybatis-config.xml),今天先來看properties標籤的解析過程。