Mybatis.net與MVC入門配置及聯合查詢動態SQL拼接和簡單事務

第一次學習Mybatis.net,在博客園也找到好多資料,但是在配置成功之後也遇到了一些問題,尤其是在動態SQl拼接時候,這裏把遇到的問題還有自己寫的一個Demo貼出來,希望能幫到新手,有不適合的地方也希望大家指出,大家互相學習,共同進步。

首先我們需要下載IBatisNet程序包,這裏就不多說了

一、創建一個MVC4的Web應用程序,並引用我們下載的IBatisNet程序包中的IBatisNet.DataMapper.dll,這裏我只引用了這一個,log4net我沒有引用也沒有配置使用,全部程序結構如下

二、添加Providers.config,並複製到項目根目錄下

把下載的IBatisNet程序包打開,就能找到providers.config文件,裏面定義了MyBatis.Net支持的各種數據庫驅動,這裏我以sqlServer爲例,把其他不用的全部刪除,只留下sqlServer的並且把版本號全部改爲4.0,同時把enabled屬性設置成true,如下:

<?xml version="1.0" encoding="utf-8"?>
<providers 
xmlns="http://ibatis.apache.org/providers" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<clear/>
  <!--設置enabled=true-->
  <provider
     name="sqlServer4.0"
     enabled="true"
     description="Microsoft SQL Server, provider V4.0.0.0 in framework .NET V4.0" 
     assemblyName="System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" 
     connectionClass="System.Data.SqlClient.SqlConnection" 
     commandClass="System.Data.SqlClient.SqlCommand"
     parameterClass="System.Data.SqlClient.SqlParameter"
     parameterDbTypeClass="System.Data.SqlDbType"
     parameterDbTypeProperty="SqlDbType"
     dataAdapterClass="System.Data.SqlClient.SqlDataAdapter"
     commandBuilderClass=" System.Data.SqlClient.SqlCommandBuilder"
     usePositionalParameters = "false"
     useParameterPrefixInSql = "true"
     useParameterPrefixInParameter = "true" 
     parameterPrefix="@"
     allowMARS="false"
    /> 
</providers>
providers.config

 三、在項目目錄下添加SqlMap.config,它的作用主要是指定db連接串,告訴系統providers.config在哪? 以及db與entity的映射文件在哪?如下:

<?xml version="1.0" encoding="utf-8"?>
<sqlMapConfig 
  xmlns="http://ibatis.apache.org/dataMapper" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  
  <settings>
    <setting useStatementNamespaces="false"/> <!--true表示statementName要使用Namespace-->
    <setting cacheModelsEnabled="true"/>
  </settings>
  
  <providers resource="providers.config"/><!--指定providers.config文件的路徑-->
  
    <!-- Database connection information -->
    <database>
        <provider name="sqlServer4.0"/><!--設置數據庫連接字符串-->
        <dataSource name="DB" connectionString="Data Source=.;Initial Catalog=DemoDB;uid=sa;pwd=123"/>
    </database>
  
  <!--db與Entity的映射文件-->
    <sqlMaps>
    <sqlMap resource="Maps/PersonAndCour.xml"/>
     <sqlMap resource="Maps/PersonMap.xml"/>
    </sqlMaps>

</sqlMapConfig>
SqlMap.config

四、這裏在數據庫建兩張表一個是個人信息還有一個是課程表,如下:

第一張表是Person表,第二張表爲Cour課程表,課程表名字是錯的只敲一半,大家略過,第一張表的ID和第二張表的PerID關聯,建兩張表是爲了後面的聯合查詢,這裏先不多說

五、接下來我們在EntityModel文件夾下建立兩個實體類一個是Person類和一個定義實體類PersonAndCour,而自定義實體類就比Person類多一個字段,就是課程名稱,這裏就只貼這一個代碼 ,如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MyBatisNet.EntityModel
{
    public class PersonAndCour
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public string Sex { get; set; }
        public string CourseName { get; set; }
    }
}
Model

六、我們在項目根目錄下建Maps文件夾,並在文件夾中創建PersonMap.xml映射文件,如下

<?xml version="1.0" encoding="utf-8" ?>
<sqlMap namespace="MyBatisNet" xmlns="http://ibatis.apache.org/mapping"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <alias>
    <!--類的別名-->
    <typeAlias alias="Person" type="MyBatisNet.EntityModel.Person,MyBatisNet"/>
  </alias>

  <resultMaps>
    <!--Person類與db表的映射-->
    <resultMap id="PersonResult" class="Person">
      <result property="ID" column="ID"/>
      <result property="Name" column="Name"/>
      <result property="Age" column="Age" />
      <result property="Sex" column="Sex"  />
    </resultMap>
  </resultMaps>

  
  <statements>
    <!--插入Sql語句-->
    <insert id="Add" parameterClass="Person" resultClass="Int32">
      insert into Person(Name,Age,Sex)values(#Name#,#Age#,#Sex#)
      <selectKey property="ID" resultClass="int" type="post" >
        SELECT @@identity AS ID
      </selectKey>
     
    </insert>
    <!--修改Sql語句-->
    <update id="Update" parameterClass="Person">
      update Person set Name=#Name#,Age=#Age#,Sex=#Sex# where ID=#ID#
    </update>

    <!--根據主鍵刪除單條記錄-->
    <delete id="Delete" parameterClass="Int32">
      delete Person where ID=#ID#
    </delete>

    <!--查詢單個實體Sql語句-->
    <select id="Get" parameterClass="Int32" resultMap="PersonResult">
      select * from Person where ID=#ID#
    </select>

    <!--查詢所有記錄-->
    <select id="GetList" resultMap="PersonResult">
    <![CDATA[select * from Person where ID<4]]>  
    </select>
  </statements>
</sqlMap>
PersonMap.xml

我們可以看到這段代碼裏有一個命名空間,如下:

這個命名空間與此文件中的 statements標籤中配置的SQL語句的id有關,在大型項目中,可能存在大量的 SQL 語句,這時候,爲每個SQL 語句起一個唯一的標識id 就變得並不容易了。爲了解決這個問題,在 mybatis 中,可以爲每個映射文件起一個唯一的命名空間,這樣,定義在這個映射文件中的每個 SQL 語句就成了定義在這個命名空間中的一個 id。只要我們能夠保證每個命名空間是唯一的,即使在不同映射文件中的語句的 id 相同,也就不會衝突了。(這段是網上覆制的),這個是在SqlMap.config配置文件中控制的,就是這個標籤 <setting useStatementNamespaces="false"/>。

七、接下來我們就要在SqlMap.config文件中配置這個映射文件的路徑了,上面的代碼裏面我們已經配好了,

八、在XML映射文件中我們已經寫好的基礎的增、刪、改、查SQL語句,接下來我們在項目中建一個Common文件夾,裏面寫一個通用的BaseDA類,裏面進行ISqlMapper的實例化,以及對MyBatis.Net做些基本的封裝(這個是網上覆制的)

using IBatisNet.DataMapper;
using IBatisNet.DataMapper.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MyBatisNet.Common
{
    public class BaseDA
    {
        public static int Insert<T>(string statementName, T t)
        {
            ISqlMapper iSqlMapper = Mapper.Instance();
            if (iSqlMapper != null)
            {
                return (int)iSqlMapper.Insert(statementName, t);
            }
            return 0;
        }

        public static int Update<T>(string statementName, T t)
        {
            ISqlMapper iSqlMapper = Mapper.Instance();
            if (iSqlMapper != null)
            {
                return iSqlMapper.Update(statementName, t);
            }
            return 0;
        }

        public static int Delete(string statementName, int primaryKeyId)
        {
            ISqlMapper iSqlMapper = Mapper.Instance();
            if (iSqlMapper != null)
            {
                return iSqlMapper.Delete(statementName, primaryKeyId);
            }
            return 0;
        }

        public static T Get<T>(string statementName, int primaryKeyId) where T : class
        {
            ISqlMapper iSqlMapper = Mapper.Instance();
            if (iSqlMapper != null)
            {
                return iSqlMapper.QueryForObject<T>(statementName, primaryKeyId);
            }
            return null;
        }

        public static IList<T> QueryForList<T>(string statementName, object parameterObject = null)
        {
            ISqlMapper iSqlMapper = Mapper.Instance();
            if (iSqlMapper != null)
            {
                return iSqlMapper.QueryForList<T>(statementName, parameterObject);
            }
            return null;
        }
    }
}
BaseDA.cs

九、現在我們就可以控制器中進行操作了

這樣我們就可以查詢到Person類的全部信息了,這裏方法中的第一個參數就是我們映射文件中SQL語句標籤中的id名稱,其他的增、刪、改都一樣,就不多說了

十,接下來我們看看我們多表聯合查詢,動態SQl拼接,以及SQL片段的使用,我們這裏用到上面的PersonAndCour.cs這個自定義類

我們先添加PersonAndCour.xml這個映射文件

<?xml version="1.0" encoding="utf-8" ?>
<sqlMap namespace="MyBatisNet" xmlns="http://ibatis.apache.org/mapping"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <alias>
    <!--類的別名-->
    <typeAlias alias="PersonAndCour" type="MyBatisNet.EntityModel.PersonAndCour,MyBatisNet"/>
  </alias>

  <resultMaps>
    <!--Product類與db表的映射-->
    <resultMap id="PersonAndCourResult" class="PersonAndCour">
      <result property="ID" column="ID"/>
      <result property="Name" column="Name"/>
      <result property="Age" column="Age" />
      <result property="Sex" column="Sex"  />
      <result property="CourseName" column="CourseName"  />
    </resultMap>
  </resultMaps>

  <statements>
    <!--sql片段,重複使用-->
    <sql id="testSql">
      select p.ID,p.Name,p.Age,p.Sex,c.CourseName from Person p
      inner join  cour c on p.ID= c.PerID
    </sql>
    
    <!--查詢所有記錄-->
    <select id="GetList1" resultMap="PersonAndCourResult">
      select p.ID,p.Name,p.Age,p.Sex,c.CourseName from Person p
      inner join  cour c on p.ID= c.PerID
    </select>
    
    <!--多條件查詢-->
    <select id="GetList2"  parameterClass="PersonAndCour" resultMap="PersonAndCourResult">
      select p.ID,p.Name,p.Age,p.Sex,c.CourseName from Person p
      inner join  cour c on p.ID= c.PerID 
      
      <dynamic perpend="where">
        <!--姓名不爲NUll-->
        <isNotEmpty property="Name" prepend="And" >
          p.Name=#Name#
        </isNotEmpty>
        <!--年齡大於0-->
        <isGreaterThan prepend="and" property="Age" compareValue="0">
          p.Age = #Age#
        </isGreaterThan>
      </dynamic>
    </select>
    
    <select id="GetList3" resultMap="PersonAndCourResult">
      <!--<include refid="sql片段" />-->
      <include refid="testSql" />
      
    </select>
  </statements>
</sqlMap>
PersonAndCour.xml

這裏面已經把SQL寫好了,現在我們在控制器裏執行,如下:

a.先說下SQL片段,我們在查詢分頁時的查詢拼接條件或都其他查詢時,可能同一段代碼重複使用,這時我們就可以利用SQL片段,把重利利用的SQL代碼提取出來,如PersonAndCour.xml裏一樣,這樣我們用<include refid="testSql" />這一句就可以引用上面的SQL語句,這裏的refid就是SQl片段中id的名字

b.再說說多條件查詢時動態拼接SQl語句,如下圖

 這裏我們傳入的參數是PersonAndCour,輸出的參數也是這個, 這個參數我們也可以自己定義,需要幾個字段就定義幾個字段,但在這裏時要寫全名比如:parameterClass="MyBatisNet.EntityModel.whereModel",還有之前在博客園找到的動態SQL拼接的都是JAVA目錄,進而是直接用<where>標籤嵌套<if>標籤,我在項目中也使用這種方式,但是<where>標籤的裏的語句就是不執行,最後在網上找了好多,最後發現用<dynamic>標籤之後裏面的語句就可以拼接成功了,原因現在還不知道,那位大神知道可以告知下,<dynamic>標籤裏面的判斷條件整理了如下幾個類型:

 (1)、一元條件

 

  (2)、二元條件

 

(3)其他

十一、最後說一下自己嘗試的事務,如果大家有更好的建議可以提出來大家一起分享

(1)、直接把事務寫在SQL語句裏面,如下

 

(1)映射文件的中還是單一的條插入SQL語句,我們在控制器中使用事務,如下:

好了,到這裏基本上已經全部寫完了,好多是在網上找的資料,有些是自己嘗試的,文章也是在做完DEMO後才寫的,所以有遺漏的地方還望見諒,有錯誤的地方,或需要改進的地方望大家提出來一起分享,共同成長。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章