MyBatis.Net 学习手记
MyBatis.NET 的前身为 IBatis,是 JAVA 版 MyBatis 在.NET 平台上的翻版,相对 NHibernate、EntityFramework 等重量级 ORM 框架而言,MyBatis.NET 必须由开发人员手动写 SQL,相对灵活性更大,更容易保证 DB 访问的性能,适用开发团队里有 SQL 熟手的场景。
下面是使用步骤:
1、到官网http://code.google.com/p/mybatisnet/ 下载相关 dll 和文档
Doc-DataAccess-1.9.2.zip
Doc-DataMapper-1.6.2.zip
IBatis.DataAccess.1.9.2.bin.zip
IBatis.DataMapper.1.6.2.bin.zip
一共有 4 个 zip 包
2、创建一个 Web 应用,参考下图添加程序集引用
3、修改 web.config,主要是配置 log4net,参考下面的内容:
1 <?xml version="1.0"?> 2 <configuration> 3 <configSections> 4 <sectionGroup name="iBATIS"> 5 <section name="logging" type="IBatisNet.Common.Logging.ConfigurationSectionHandler, IBatisNet.Common"/> 6 </sectionGroup> 7 <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/> 8 </configSections> 9 <system.web> 10 <compilation debug="true" targetFramework="4.0"/> 11 </system.web> 12 <iBATIS> 13 <logging> 14 <logFactoryAdapter type="IBatisNet.Common.Logging.Impl.Log4NetLoggerFA, IBatisNet.Common.Logging.Log4Net"> 15 <arg key="configType" value="inline"/> 16 <arg key="showLogName" value="true"/> 17 <arg key="showDataTime" value="true"/> 18 <arg key="level" value="ALL"/> 19 <arg key="dateTimeFormat" value="yyyy/MM/dd HH🇲🇲ss:SSS"/> 20 </logFactoryAdapter> 21 </logging> 22 </iBATIS> 23 <log4net> 24 <!-- Define some output appenders --> 25 <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender"> 26 <param name="File" value="mybatis.log"/> 27 <param name="AppendToFile" value="true"/> 28 <param name="MaxSizeRollBackups" value="2"/> 29 <param name="MaximumFileSize" value="100KB"/> 30 <param name="RollingStyle" value="Size"/> 31 <param name="StaticLogFileName" value="true"/> 32 <layout type="log4net.Layout.PatternLayout"> 33 <param name="Header" value="[Header]\r\n"/> 34 <param name="Footer" value="[Footer]\r\n"/> 35 <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] - %m%n"/> 36 </layout> 37 </appender> 38 <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender"> 39 <layout type="log4net.Layout.PatternLayout"> 40 <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] <%X{auth}> - %m%n"/> 41 </layout> 42 </appender> 43 <!-- Set root logger level to ERROR and its appenders --> 44 <root> 45 <level value="DEBUG"/> 46 <appender-ref ref="RollingLogFileAppender"/> 47 <appender-ref ref="ConsoleAppender"/> 48 </root> 49 <!-- Print only messages of level DEBUG or above in the packages --> 50 <logger name="IBatisNet.DataMapper.Configuration.Cache.CacheModel"> 51 <level value="DEBUG"/> 52 </logger> 53 <logger name="IBatisNet.DataMapper.Configuration.Statements.PreparedStatementFactory"> 54 <level value="DEBUG"/> 55 </logger> 56 <logger name="IBatisNet.DataMapper.LazyLoadList"> 57 <level value="DEBUG"/> 58 </logger> 59 <logger name="IBatisNet.DataAccess.DaoSession"> 60 <level value="DEBUG"/> 61 </logger> 62 <logger name="IBatisNet.DataMapper.SqlMapSession"> 63 <level value="DEBUG"/> 64 </logger> 65 <logger name="IBatisNet.Common.Transaction.TransactionScope"> 66 <level value="DEBUG"/> 67 </logger> 68 <logger name="IBatisNet.DataAccess.Configuration.DaoProxy"> 69 <level value="DEBUG"/> 70 </logger> 71 </log4net> 72 </configuration>
4、添加 Providers.config
把从官方下载的压缩包解开,就能找到 providers.config 文件,里面定义了 MyBatis.Net 支持的各种数据库驱动,本例以 oracle 为例,把其它不用的 db provider 全删掉,只保留下 oracleClient1.0,同时把 enabled 属性设置成 true,参考下面这样:
1 <?xml version="1.0"?> 2 <providers xmlns="http://ibatis.apache.org/providers" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4 5 <clear/> 6 7 <!--Oracle Support--> 8 <provider 9 name="oracleClient1.0" 10 description="Oracle, Microsoft provider V1.0.5000.0" 11 enabled="true" 12 assemblyName="System.Data.OracleClient, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" connectionClass="System.Data.OracleClient.OracleConnection" 13 commandClass="System.Data.OracleClient.OracleCommand" 14 parameterClass="System.Data.OracleClient.OracleParameter" 15 parameterDbTypeClass="System.Data.OracleClient.OracleType" 16 parameterDbTypeProperty="OracleType" 17 dataAdapterClass="System.Data.OracleClient.OracleDataAdapter" 18 commandBuilderClass="System.Data.OracleClient.OracleCommandBuilder" 19 usePositionalParameters="false" 20 useParameterPrefixInSql="true" 21 useParameterPrefixInParameter="false" 22 parameterPrefix=":" 23 allowMARS="false" 24 /> 25 26 </providers>
把这个文件复制到 Web 项目根目录下
5、添加 SqlMap.config,内容如下:
1 <?xml version="1.0" encoding="utf-8"?> 2 <sqlMapConfig xmlns="http://ibatis.apache.org/dataMapper" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4 5 <settings> 6 <setting useStatementNamespaces="false"/> 7 <setting cacheModelsEnabled="true"/> 8 </settings> 9 10 <!--db provider 配置文件路径--> 11 <providers resource="providers.config"/> 12 13 <!--db provider 类型及连接串--> 14 <database> 15 <provider name="oracleClient1.0" /> 16 <dataSource name="oracle" connectionString="Data Source=ORCL;Persist Security Info=True;User ID=scott;Password=tiger;Unicode=True" /> 17 </database> 18 19 <!--db 与 Entity 的映射文件--> 20 <sqlMaps> 21 <sqlMap resource="Maps/ProductMap.xml"/> 22 </sqlMaps> 23 24 </sqlMapConfig>
这个文件也复制到 Web 项目根目录下,它的作用主要是指定 db 连接串,告诉系统 providers.config 在哪? 以及 db 与 entity 的映射文件在哪?(映射文件后面会讲到,这里先不管)
6、在 Oraccle 中先建表 Product 以及 Sequence,方便接下来测试
1 -- CREATE TABLE 2 CREATE TABLE PRODUCT 3 ( 4 PRODUCTID NUMBER NOT NULL, 5 PRODUCTNAME VARCHAR2(100), 6 PRODUCTCOMPANY VARCHAR2(100), 7 SIGNDATE DATE, 8 UPDATEDATE DATE 9 ); 10 -- CREATE/RECREATE PRIMARY, UNIQUE AND FOREIGN KEY CONSTRAINTS 11 ALTER TABLE PRODUCT 12 ADD CONSTRAINT PK_PRODUCT_ID PRIMARY KEY (PRODUCTID); 13 14 -- CREATE SEQUENCE 15 CREATE SEQUENCE SQ_PRODUCT 16 MINVALUE 1 17 MAXVALUE 9999999999999999999999999 18 START WITH 1 19 INCREMENT BY 1 20 CACHE 20;
7、创建 Maps 目录,并在该目录下,添加映射文件 ProductMap.xml,内容如下:
1 <?xml version="1.0" encoding="utf-8" ?> 2 <sqlMap namespace="EntityModel" xmlns="http://ibatis.apache.org/mapping" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4 5 <alias> 6 <!--类的别名--> 7 <typeAlias alias="Product" type="Web.Product,Web"/> 8 </alias> 9 10 <resultMaps> 11 <!--Product 类与 db 表的映射--> 12 <resultMap id="SelectAllResult" class="Product"> 13 <result property="ProductId" column="ProductId"/> 14 <result property="ProductName" column="ProductName"/> 15 <result property="ProductCompany" column="ProductCompany" /> 16 <result property="SignDate" column="SignDate" /> 17 <result property="UpdateDate" column="UpdateDate" /> 18 </resultMap> 19 </resultMaps> 20 21 <statements> 22 23 <!--查询所有记录--> 24 <select id="SelectAllProduct" resultMap="SelectAllResult"> 25 <![CDATA[SELECT ProductId,ProductName,ProductCompany,SignDate,UpdateDate FROM Product]]> 26 </select> 27 28 <!--查询单条记录--> 29 <select id="SelectByProductId" parameterClass="int" resultMap="SelectAllResult" extends="SelectAllProduct"> 30 <![CDATA[ where ProductId = #value#]]> 31 </select> 32 33 <!--插入新记录--> 34 <insert id="InsertProduct" parameterClass="Product"> 35 <!--oracle sequence 的示例用法--> 36 <selectKey property="ProductId" type="pre" resultClass="int"> 37 select SQ_Product.nextval as ProductId from dual 38 </selectKey> 39 <![CDATA[INSERT into Product(ProductId,ProductCompany,ProductName,SignDate,UpdateDate) 40 VALUES(#ProductId#,#ProductCompany#, #ProductName# , #SignDate# , #UpdateDate#)]]> 41 </insert> 42 43 <!--更新单条记录--> 44 <update id="UpdateProduct" parameterClass="Product"> 45 <![CDATA[Update Product SET ProductName=#ProductName#, 46 ProductCompany=#ProductCompany#, 47 SignDate=#SignDate#, 48 UpdateDate=#UpdateDate# 49 Where ProductId=#ProductId#]]> 50 </update> 51 52 <!--根据主键删除单条记录--> 53 <delete id="DeleteProductById" parameterClass="int"> 54 <![CDATA[Delete From Product Where ProductId=#value#]]> 55 </delete> 56 57 58 </statements> 59 60 </sqlMap>
它的作用就是指定各种 sql,以及 db 表与 entity 的映射规则,注意下 insert 中 Sequence 的用法!
8、创建实体类 Product
1 using System; 2 3 namespace Web 4 { 5 public class Product 6 { 7 public int ProductId { get; set; } 8 public string ProductName { get; set; } 9 public string ProductCompany { get; set; } 10 public DateTime SignDate { get; set; } 11 public DateTime UpdateDate { get; set; } 12 13 public Product(){} 14 } 15 }
9、写一个通用的 BaseDA 类,对 MyBatis.Net 做些基本的封装
1 using IBatisNet.DataMapper; 2 using System.Collections.Generic; 3 4 namespace Web 5 { 6 public static class BaseDA 7 { 8 public static int Insert<T>(string statementName, T t) 9 { 10 ISqlMapper iSqlMapper = Mapper.Instance(); 11 if (iSqlMapper != null) 12 { 13 return (int)iSqlMapper.Insert(statementName, t); 14 } 15 return 0; 16 } 17 18 public static int Update<T>(string statementName, T t) 19 { 20 ISqlMapper iSqlMapper = Mapper.Instance(); 21 if (iSqlMapper != null) 22 { 23 return iSqlMapper.Update(statementName, t); 24 } 25 return 0; 26 } 27 28 public static int Delete(string statementName, int primaryKeyId) 29 { 30 ISqlMapper iSqlMapper = Mapper.Instance(); 31 if (iSqlMapper != null) 32 { 33 return iSqlMapper.Delete(statementName, primaryKeyId); 34 } 35 return 0; 36 } 37 38 public static T Get<T>(string statementName, int primaryKeyId) where T : class 39 { 40 ISqlMapper iSqlMapper = Mapper.Instance(); 41 if (iSqlMapper != null) 42 { 43 return iSqlMapper.QueryForObject<T>(statementName, primaryKeyId); 44 } 45 return null; 46 } 47 48 public static IList<T> QueryForList<T>(string statementName, object parameterObject = null) 49 { 50 ISqlMapper iSqlMapper = Mapper.Instance(); 51 if (iSqlMapper != null) 52 { 53 return iSqlMapper.QueryForList<T>(statementName, parameterObject); 54 } 55 return null; 56 } 57 } 58 }
10、然后就可以在 Default.aspx.cs 上测试了,参考下面的代码:
using System; using System.Web.UI;namespace Web
{
public partial class Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
//插入
var insertProductId = BaseDA.Insert<Product>("InsertProduct", new Product()
{
ProductCompany = "INFOSKY",
ProductName = "iGSA2",
SignDate = DateTime.Now,
UpdateDate = DateTime.Now
});</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">查单条记录</span> <span style="color: rgba(0, 0, 255, 1)">var</span> model = BaseDA.Get<Product>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">SelectByProductId</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, insertProductId); ShowProduct(model); Response.Write(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"><hr/></span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">修改记录</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (model != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) { model.ProductName </span>= (<span style="color: rgba(0, 0, 255, 1)">new</span> Random().Next(<span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 128, 1)">99999999</span>)).ToString().PadLeft(<span style="color: rgba(128, 0, 128, 1)">10</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">0</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 0, 255, 1)">int</span> updateResult = BaseDA.Update<Product>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">UpdateProduct</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, model); Response.Write(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">update影响行数:</span><span style="color: rgba(128, 0, 0, 1)">"</span> + updateResult + <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"><br/><hr/></span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">); } </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">查列表</span> <span style="color: rgba(0, 0, 255, 1)">var</span> products = BaseDA.QueryForList<Product>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">SelectAllProduct</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> pro <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> products) { ShowProduct(pro); } Response.Write(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"><hr/></span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">删除记录</span> <span style="color: rgba(0, 0, 255, 1)">int</span> deleteResult = BaseDA.Delete(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DeleteProductById</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, insertProductId); Response.Write(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">delete影响行数:</span><span style="color: rgba(128, 0, 0, 1)">"</span> + deleteResult + <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)"><br/><hr/></span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">); } </span><span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> ShowProduct(Product pro) { </span><span style="color: rgba(0, 0, 255, 1)">if</span> (pro == <span style="color: rgba(0, 0, 255, 1)">null</span>) <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">; Response.Write(</span><span style="color: rgba(0, 0, 255, 1)">string</span>.Format(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{0}&nbsp;,&nbsp;{1}&nbsp;,&nbsp;{2}&nbsp;,&nbsp;{3}&nbsp;,&nbsp;{4}<br/></span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, pro.ProductId, pro.ProductName, pro.ProductCompany, pro.SignDate, pro.UpdateDate)); } }
}
整个项目的目录结构如下: