首先,MyBatis 封装了绝大多数的数据访问代码,使得开发者只需关注 SQL 本身,而不需要花费精力去处理像创建 Connection,以及确保关闭 Connection 这样繁杂的代码。
其次,MyBatis 可以算是在所有主流的持久层框架中学习成本最低,最容易上手和掌握的框架。虽说其他持久层框架也号称门槛低,容易上手,但是等到你真正使用时会发现,要想掌握并用好它是一件非常困难的事。
考虑我们希望访问数据库中的产品表,表的名称为:[Production].[Products],表的结构如下所示:
为了简单起见,我们仅仅读取前两个字段:productit 和 productname。
在项目中,我们希望读取的数据被转换为实体对象,当然,我们需要定义一个类来表示这个映射关系。
在 EntityModel 项目中,我们定义了一个实体类 Product。读取的数据将被转换为这个类的对象实例。这个类不需要实现任何接口,也不需要从任何特殊的基类派生。
namespace EntityModel { public class Product { public int ProductId { get; set; } public string ProductName { get; set; } } }
这步映射一般通过 XML 文件完成,文件名任意,并没有特殊的要求,关键是映射文件必须符合特定的架构要求。这个架构要求在 MyBatisNet 的压缩包中存在,名为:SqlMap.xsd。
文件中主要包含三个部分。
为了在 XML 文件中便于描述,可以为涉及的数据类型创建一个别名,例如,为 Product 类创建别名 Product, 如下所示,type 是原有的 .NET 类型表示,typeAlias 就是我们定义的别名。
<alias> <typeAlias alias="Product" type="EntityModel.Product, EntityModel"/> </alias>
这里定义查询结果中的字段与实体对象的属性之间的映射关系,可以在 resultMaps 中包含多个映射,每个映射通过 resultMap 进行描述。
其中:id 用于后面的 SQL 定义中使用,class 指的是我们定义的实体类,这里使用了上面定义的别名。
每一个 result 中的 property 用来描述实体类的属性,type 是实体类的类型,column 是对应的查询字段名称,dbType 就是数据库字段的类型了。
<resultMaps> <!-- 映射可以用在下面的语句设置中 --> <resultMap id="GetAllProductsResult" class="Product"> <result property="ProductId" type="int" column="ProductId" dbType="int" /> <result property="ProductName" type="string" column="ProductName" dbType="nvarchar" /> </resultMap> </resultMaps>
在 MyBatisNet 中,SQL 不用写在代码中,而是写在映射文件中。
下面提供了两个查询定义,注意每个查询的 id 不同,以后在代码中,通过这个 id 来查询对应的 SQL 语句。
resultClass 和 resultMap 用来配置查询结果应该转化为何种类型的对象实例,映射的名字就是 3.2 中定义的映射名。
<![CDATA[ 和 ]]> 是 XML 中对于不需转义的内容的特殊标识形式,等同于 C# 中字符串之前的 @ 符号,比较特殊一点。
<statements> <!-- resultClass 直接设置返回的类型 --> <!-- resultMap 通过映射设置返回类型 --> <select id="GetAllProducts" resultMap="GetAllProductsResult"> <![CDATA[ SELECT productid, productname FROM [Production].Products ]]> </select> <select id="GetProductById" parameterClass="int" resultMap="GetAllProductsResult"> <![CDATA[ select productid, productname from [Production].Products where productid = #value# ]]> </select> </statements>
完整的映射配置如下所示:
<?xml version="1.0" encoding="utf-8" ?> <sqlMap namespace="EntityModel" xmlns="http://ibatis.apache.org/mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <alias> <typeAlias alias="Product" type="EntityModel.Product, EntityModel"/> </alias> <resultMaps> <!-- 映射可以用在下面的语句设置中 --> <resultMap id="GetAllProductsResult" class="Product"> <result property="ProductId" type="int" column="ProductId" dbType="int" /> <result property="ProductName" type="string" column="ProductName" dbType="nvarchar" /> </resultMap> </resultMaps> <statements> <!-- resultClass 直接设置返回的类型 --> <!-- resultMap 通过映射设置返回类型 --> <select id="GetAllProducts" resultMap="GetAllProductsResult"> <![CDATA[ SELECT productid, productname FROM [Production].Products ]]> </select> <select id="GetProductById" parameterClass="int" resultMap="GetAllProductsResult"> <![CDATA[ select productid, productname from [Production].Products where productid = #value# ]]> </select> </statements> </sqlMap>
访问不同类型的数据库,需要用到一些不同的类型和写法,这些信息 MyBatisNet 已经帮我们准备好了,providers.config 文件就是,我们并不需要做什么。
唯一需要注意的就是对于我们需要使用的数据访问类型,必须将 enabled 配置为 true。
比如,你希望使用 SQL2005 方式,那么就将这一段的 enabled 设置为 true.
需要记住你使用的提供器的 name, 在后面会使用到的。
<provider name="sqlServer2005" enabled="true" description="Microsoft SQL Server, provider V2.0.0.0 in framework .NET V2.0" assemblyName="System.Data, Version=2.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="true" />
SqlMap.config 是 MyBatisNet 的顶级配置文件,各个部分通过它粘和在一起。
属性类似于程序中的变量,定义之后,可以在后面的配置中使用名称来表示其中的值,这样,以后我们就可以直接修改变量了。
定义之后,在使用的使用通过 ${属性名} 使用。比如,在后面的数据库连接串中,就可以直接使用属性名了。
<!-- 属性可以在后面使用, 使用的时候通过 ${属性名引用} --> <properties> <property key="datasource" value=".\sqlexpress" /> <property key="database" value="TSQLFundamentals2008" /> <property key="selectKey" value="select scope_identity() as value" /> <property key="directory" value="MapFiles" /> <property key="useStatementNamespaces" value="false" /> </properties>
配置 MyBatisNet 的一些参数
<!--Basic Setting About Configuration--> <settings> <setting useStatementNamespaces="false"/> <setting cacheModelsEnabled="true"/> </settings>
还记得 4 中的数据访问的配置信息吗?我们保存在一个文件中,这里配置如何找到它。
<!-- 设置 provider 文件的来源,这个文件一般直接使用 myBatisNet 提供的文件 --> <providers resource="providers.config"/>
数据库连接串,数据库连接使用的 provider ,这个名字就是我们在 4 中曾经启用的那个。
<!--数据库连接--> <database> <!-- provider 名字来自文件 providers.config 这个文件由 myBatisNet提供,直接使用即可 注意:这里使用的 provider 需要在 providers.config 中设置为启用 enabled="true" --> <provider name="sqlServer2005" /> <dataSource name="iBatisNet" connectionString="data source=${datasource};database=${database};integrated security=true;" /> </database>
这里直接使用文件格式,注意要将文件复制到程序的执行目录下。
<!-- 映射文件位置 --> <sqlMaps> <sqlMap resource="Maps/ProductMap.xml"/> </sqlMaps>
完整的配置文件如下:
<?xml version="1.0" encoding="utf-8" ?> <sqlMapConfig xmlns="http://ibatis.apache.org/dataMapper" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <!-- 属性可以在后面使用, 使用的时候通过 ${属性名引用} --> <properties> <property key="datasource" value=".\sqlexpress" /> <property key="database" value="TSQLFundamentals2008" /> <property key="selectKey" value="select scope_identity() as value" /> <property key="directory" value="MapFiles" /> <property key="useStatementNamespaces" value="false" /> </properties> <!--Basic Setting About Configuration--> <settings> <setting useStatementNamespaces="false"/> <setting cacheModelsEnabled="true"/> </settings> <!-- 设置 provider 文件的来源,这个文件一般直接使用 myBatisNet 提供的文件 --> <providers resource="providers.config"/> <!--数据库连接--> <database> <!-- provider 名字来自文件 providers.config 这个文件由 myBatisNet提供,直接使用即可 注意:这里使用的 provider 需要在 providers.config 中设置为启用 enabled="true" --> <provider name="sqlServer2005" /> <dataSource name="iBatisNet" connectionString="data source=${datasource};database=${database};integrated security=true;" /> </database> <!-- 映射文件位置 --> <sqlMaps> <sqlMap resource="Maps/ProductMap.xml"/> </sqlMaps> </sqlMapConfig>
在 MyBatisNet 中,我们需要获取 ISqlMapper 对象来访问数据,这个对象 MyBatisNet 中已经定义了一个静态方法,我们可以直接使用。
IBatisNet.DataMapper.Mapper.Instance()
使用注入方式,定义如下的数据访问对象。
public class ProductDao { // private static SqlMapper sqlMapper = null; public ISqlMapper Mapper { set; get; } static ProductDao() { // 现在 IBatisNet.DataMapper.Mapper.Instance() 内部就已经完成了下面的操作 // DomSqlMapBuilder builder = new DomSqlMapBuilder(); // sqlMapper = builder.Configure() as SqlMapper; } public IList<EntityModel.Product> GetProductList() { IList<EntityModel.Product> productList = Mapper.QueryForList<EntityModel.Product>("GetAllProducts", null); return productList; } public EntityModel.Product GetProductById(int id) { EntityModel.Product product = Mapper.QueryForObject<EntityModel.Product>("GetProductById", 1); return product; } }
其中 Mapper 等待注入,查询单个对象使用了 Mapper 的 QueryForObject 泛型方法,查询多个对象使用了 QueryForList 方法,参数就是 SQL 映射中定义的 id。
主程序中创建数据访问对象,注入 Mapper ,完成数据访问。
DataMapperStart.ProductDao crud = new DataMapperStart.ProductDao(); // 默认配置文件使用 SqlMap.config crud.Mapper = IBatisNet.DataMapper.Mapper.Instance(); EntityModel.Product p = crud.GetProductById(1); Console.WriteLine(p.ProductName); Console.WriteLine(); IList<EntityModel.Product> list = crud.GetProductList(); foreach (EntityModel.Product product in list) { Console.WriteLine("Product Id: {0}, Name: {0}", product.ProductId, product.ProductName); }
总结:
看起来步骤很多,实际上主要涉及到三个配置文件,代码非常的简单。MyBatisNet 提供了 XML 的架构文件,在 VS 中可以实现 XML 的提示,写起来其实很方便。