分享

Mybatis.net与MVC入门配置及联合查询动态SQL拼接和简单事务

 若生安饶 2024-04-09 发布于北京

引用地址 https://www.cnblogs.com/happy-tears/p/4442260.html 

第一次学习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./providers' 
xmlns:xsi='http://www./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./dataMapper' 
  xmlns:xsi='http://www./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./mapping'
         xmlns:xsi='http://www./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./mapping'
         xmlns:xsi='http://www./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后才写的,所以有遗漏的地方还望见谅,有错误的地方,或需要改进的地方望大家提出来一起分享,共同成长。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多