1. 程式人生 > >Mybatis(1)

Mybatis(1)

一、MyBatis的HelloWorld

   1. 使用底層的selectOne()方法

   /**

   * helloWorld的小結:

   *

   * 1.匯入Mybatis的jar包

   * 2.建立一個全域性配置檔案  mybatis-config.xml ,根據全域性配置檔案,建立了一個

          SqlSessionFactory物件.

   * 3.建立一個sql對映檔案, EmployeeMapper.xml,該配置檔案中配置了sql語句.

   * 4.將sql對映檔案註冊到全域性配置檔案中

   * 5.從SqlSessionFactory中獲取SqlSession物件. sqlSession代表和資料庫的一次會話.

   *    然後呼叫selectOne("sql語句的唯一標識",執行sql的引數)完成查詢操作.

   * 6.最後將SqlSession物件關閉.釋放資源.

   */

2. 使用Mapper介面開發    

   /**

   *  Mapper介面的好處:

   *  1.介面中定義的方法明確的型別約束(方法引數的型別   方法返回值的型別)

   *      2.介面本身:

   *        介面本身就是抽象.抽出了規範.不強制要求如何做具體的實現.可以使用jdbc,

                hibernate,Mybatis.

   *        介面將規範與具體的實現分離.

   *  Mapper介面開發, MyBatis會為介面生成代理實現類。代理物件完成具體的增刪改查操作.

   *  最底層還是使用selectOne,update等方法來完成的.

   * 

   *  Mapper介面開發需要注意:

   *  1.Mapper介面要與sql對映檔案動態繫結. sql對映檔案的namespace指定成介面的全類名.

   *      2.Mapper介面方法與sql對映檔案的sql語句繫結。  sql語句的id值指定成介面中的方法名.

   */

二、全域性配置檔案

1.properties

 <!--

     1.properties: Mybatis可以是用properties來引入外部properties型別的檔案.

       resource: 引入類路徑下的資源

       url: 引入網路路徑或者是磁碟路徑下的資源

   -->

   <properties resource="db.properties" ></properties>

2.settings

<!--

     2.settings: 包含了很多重要的設定項

       setting: 用來設定每一個設定項

       name:設定項的名稱

       value:設定項的值

-->

<settings>

    <!-- 自動對映下劃線到駝峰命名    DB: last_name  autoMapping  lastName -->

    <setting name="mapUnderscoreToCamelCase" value="true"/>

</settings>

3.typeAliases

<!--

    3.typeAliases:別名處理,為java 型別註冊別名

       typeAlias: 為某個java類指定別名

         type: 指定java的型別(包名+ 類名

         alias: 指定具體的別名。 如果alias不顯示的指定,則預設的別名是類名的首字母小

                       寫.

              別名不區分大小寫。

       package: 批量取別名.

          name:指定包名。   為該包下的所的類取預設的別名。

          批量取別名可能會出現別名衝突的情況. 例如指定的包下與子包下相同的類.

          可以使用@Alias("別名")在類上標註具體的別名.

 -->

<typeAliases> 

   <package name="com.xypuxing.mybatis.beans"/>

   <!-- <typeAlias type="com.xypuxing.mybatis.beans.Employee" alias="emp" /> -->

</typeAliases>

4.environments

<!--

     4.environments: 環境們。  使用default來指定具體使用的環境.

        environment:配置具體的環境.

         id: 當前環境的標識

         transactionManager:事務管理器

            type: 配置具體的事務管理器的型別

              JDBC: JdbcTransactionFactory

              MANAGED:ManagedTransactionFactory    

         最終: 事務管理要交給Spring. 使用Spring的宣告式事務.   

         dataSource:資料來源

            type: 執行資料來源的型別.

              UNPOOLED:不是用連線池 UnpooledDataSourceFactory

              POOLED:使用連線池  PooledDataSourceFactory

              JNDI:從web伺服器中獲取資料來源.  JndiDataSourceFactory    

         最終: 資料來源交給Spring管理
-->

<environments default="mysql">

    <environment id="mysql">

       <transactionManager type="JDBC" />

       <dataSource type="POOLED">

         <property name="driver" value="${jdbc.driver}" />

         <property name="url" value="${jdbc.url}" />

         <property name="username" value="${jdbc.username}" />

         <property name="password" value="${jdbc.password}" />

       </dataSource>

    </environment>

</environments>

5.databaseIdProvider

<!--

     5.databaseIdProvider:

       Mybatis用來支援多資料庫廠商。Mybatis可以根據不同的資料庫執行不同的sql語句

       DB_VENDOR: VendorDatabaseIdProvider 作用就是得到資料庫廠商的標識名.

               Connection.getMetaData().getDataBaseProductName();

       常見的資料庫廠商的標識名:

         MySQL:  MySQL

         Oracle: Oracle

         SQL Server:  SQL Server  

-->

   <databaseIdProvider type="DB_VENDOR">

    <!-- 為資料庫廠商的標識名起別名 -->

    <property name="MySQL" value="mysql"/>

    <property name="Oracle" value="oracle"/>

    <property name="SQL Server" value="sqlserver"/>

   </databaseIdProvider>

6.mappers     

<!--

     6.mappers: 引入sql對映檔案

       mapper: 引入單個的sql對映檔案

         resource: 引入類路徑下的sql對映檔案

         url:引入網路路徑或者是磁碟路徑下的sql對映檔案.

         package: 批量引入sql對映檔案

             要求:

               1.sql對映檔案的名字與 Mapper介面的名字一致.

               2.Sql對映檔案與Mapper介面必須在同一目錄下.

         name:指定包名          

-->

<mappers>

    <!-- <mapper resource="mybatis/config/EmployeeMapper.xml"/> -->

    <package name="com.xypuxing.mybatis.dao"/>

</mappers>

三、sql對映檔案

1.增刪改查

<insert id=""  parameterType="" databaseId="" >

     <update>

     <delete>

     <select id="" parameterType="" resultType=""  databaseId="">

如果想要獲取到增刪改對資料的影響條數,可以直接在介面的方法中宣告返回值型別即可.

2.主鍵自增以及主鍵值的返回

a.對於支援自增主鍵的資料庫(Mysql),可以使用useGeneratedKeys="true" keyProperty="javaBean的屬性"

b.對於不支援自增主鍵的資料庫(oracle),使用selectKey的子標籤完成主鍵值得返回.
  selectKey的用法:
  BEFORE: selectKey在插入語句之前執行
  AFTER:  selectKey在插入語句之後執行

c.Oracle資料庫的自增策略:

使用序列模擬自增. 可以從序列中查詢 nextval  currval.

3.引數傳遞:

單個引數(普通型別(基本型別/包裝型別+String)):  Mybatis不會做特殊的處理

       取值: #{引數名(隨便寫)} 取出引數值

    多個引數:MyBatis會做特殊處理. 多個引數會被封裝成一個Map。

      封裝map的規則:

      key: param1 ,param2 , param3 ..... paramN / 0 1 2 ....N-1

      value:具體傳入的引數值

      異常: ### Cause: org.apache.ibatis.binding.BindingException: Parameter 'id' not found.

             Available  parameters are [1, 0, param1, param2]

      解決: 取值使用#{param1/ 0}  #{param2 / 1 }

命名引數**: 明確的指定多個引數封裝map的時候所使用的key。   @Param("key")

      取值: #{@Param指定的key/paramN}

POJO:  如果引數很多,正好又是業務邏輯的資料模型中的屬性,直接傳入POJO

      取值: #{POJO的屬性名}

Map: 如果引數很多,不是業務邏輯的資料模型中的屬性,可以封裝成map傳入.

      取值: #{map中的key}

引數處理的原始碼分析:

names={0=id,1=lastName}

args=[1001,Tom]

public Object getNamedParams(Object[] args) {

    final int paramCount = names.size();

    if (args == null || paramCount == 0) {

      return null;

    } else if (!hasParamAnnotation && paramCount == 1) {

      return args[names.firstKey()];

    } else {

      final Map<String, Object> param = new ParamMap<Object>();

      int i = 0;

      for (Map.Entry<Integer, String> entry : names.entrySet()) {

        param.put(entry.getValue(), args[entry.getKey()]);

        // add generic param names (param1, param2, ...)

        final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1);

        // ensure not to overwrite parameter named with @Param

        if (!names.containsValue(genericParamName)) {

          param.put(genericParamName, args[entry.getKey()]);

        }

        i++;

      }

      return param;

    }

     

引數值的獲取方式:

#{}: 可以獲取map中的值 或者是POJO物件屬性的值。 還可以直接獲取普通型別的引數.

${}: 可以獲取map中的值 或者是POJO物件屬性的值



區別:

#{}:是以預編譯的形式將引數設定到sql語句中. PreparedStatement  防止sql注入.

${}:取出的值直接拼裝到sql語句中.會有安全問題.

使用場景:

   大部分情況下推薦使用#{},原生的jdbc不支援佔位符的地方可以使用${}來進行動態的賦值.

   eg: select  xxxxx    from    where  條件  order by 排序欄位  排序方式  limit ?,?;

   分表:

      select * from 2016_salary ;

      select * from 2017_salary ;

      select * from ${year}_salary ;

      使用者選擇2016年,則從2016_salary表查.