『Spring.NET+NHibernate+泛型』框架搭建之DAO(三)★
? 本節內容介紹Nhibernate所封裝的數據庫訪問層。只是我增加了泛型進行封裝。大概思路:首先,我們有一個接口層,另一個相應的實現層。在接口層中我們先定義一個父接口,父接口中定義每個接口都可能會用到的方法,然后其它接口繼承此父接口即可。假設子接口須要使用特殊的方法,能夠單獨定義在子接口中;在接口實現層中也是類似的,定義一個父類,里面寫好實現了接口層父接口的方法。其它實現層相同繼承父接口和實現層父類,接口層中定義的特殊方法也在相應的實現類中進行實現。這樣做能夠有效的把相似的反復代碼(反復的增刪改查)盡可能的降低。而且這樣設計比較靈活,反復的寫一次即可了,特殊的單獨寫。維護起來也比較方便。這樣描寫敘述可能不是非常明確,以下具體介紹實現步驟。
一、數據庫訪問接口層IDAO
? 1. 在解決方式上右鍵新建一個類庫,命名為IDAO,用來存放Nhibernae數據庫訪問接口層代碼,并加入引用上一節所講的實體層Model;
? 2. 在類庫中加入一個父接口,命名為IDAO,并定義經常使用的方法,代碼例如以下:
using System; using System.Collections.Generic; using System.Linq; using System.Text;namespace IDAO {public interface IDAO<T>{/// <summary>/// 加入實體/// </summary>/// <param name="entity"></param>int Add(T entity);/// <summary>/// 改動實體/// </summary>/// <param name="entity"></param>void Update(T entity);/// <summary>/// 保存或改動實體/// </summary>/// <param name="customer"></param>void SaveOrUpdate(IList<T> list);/// <summary>/// 刪除實體/// </summary>/// <param name="entity"></param>void Delete(T entity);/// <summary>/// 按條件刪除/// </summary>/// <param name="sqlWhere">刪除條件</param>void Delete(string sqlWhere);/// <summary>/// 依據ID得到實體/// </summary>/// <param name="id"></param>/// <returns></returns>T Get(int id);/// <summary>/// 依據ID得到實體/// </summary>/// <param name="id"></param>/// <returns></returns>T Load(int id);/// <summary>/// 得到全部實體/// </summary>/// <returns></returns>IList<T> LoadAll();/// <summary>/// 按條件排序得到前N條記錄/// </summary>/// <param name="top">獲取條數</param>/// <param name="field">排序字段</param>/// <param order="field">排序方式,升序asc,降序desc</param>/// <returns></returns>IList<T> QueryTop(int top, string field, string order);/// <summary>/// 依據條件得到實體/// </summary>/// <param name="sqlWhere">查詢條件</param>/// <returns></returns>IList<T> Where(string sqlWhere);/// <summary>/// 得到統計數量/// </summary>/// <param name="strWhere">查詢條件</param>/// <returns></returns>int GetRecordCount(string strWhere);/// <summary>/// 分頁獲取數據列表/// </summary>/// <param name="PageSize">每頁獲取數據條數</param>/// <param name="PageIndex">當前頁是第幾頁</param>/// <param name="strWhere">查詢條件</param>/// <returns></returns>IList<T> GetPageList(int PageSize, int PageIndex, string strWhere);/// <summary>/// 依據數據字典父編碼和編碼獲取名稱/// </summary>/// <param name="parentNumber">父編碼</param>/// <param name="number">編碼</param>/// <returns></returns>string GetName(string parentNumber, string number);/// <summary>/// 獲取該父編碼下最大編碼/// </summary>/// <param name="parentNumber">父編碼</param>/// <returns></returns>int GetMaxNumber(string parentNumber);} }??3.定義好了父接口,以下定義子接口,還是以IT_RoleDAO為例。代碼例如以下:
using System; using Model;namespace IDAO {public interface IT_RoleDAO : IDAO<T_Role>{} }? 這樣。IT_RoleDAO就擁有了IDAO定義了的方法,假設IT_RoleDAO有特殊方法。直接加入在IT_RoleDAO里面就可以。以IT_AreaDAO為例,代碼例如以下:
using System; using Model;namespace IDAO {public interface IT_AreaDAO : IDAO<T_Area>{/// <summary>/// 獲取/// </summary>/// <param name="parentNumber"></param>/// <returns></returns>int GenerateAreaNumber(string parentNumber);} }? 最后,我們看一下IDAO層的文件文件夾:
二、NHibernate數據庫訪問實現層NHibernateDAO(核心)
? 1. 在解決方式上右鍵新建一個類庫。命名為NHibernateDAO,用來存放Nhibernae數據庫訪問實現層代碼,并加入引用上一節所講的實體層Model和接口層IDAO;
??2. 右鍵點擊引用,選擇“管理NuGet程序包”,選擇“聯機”,搜索“Spring.NET”,在搜索結果中選擇“Spring.Net NHibernate 4 support”安裝。該安裝包含了一個NHibernate,可是還不夠,相同的方法搜索NHibernate,并安裝,加入Nhibernate就不上圖了。加入Spring.NET的界面圖例如以下:
? 3.加入數據庫訪問層父類NHibernateDAO。NHibernateDAO類中的SessionFactory屬性的GetCurrentSession方法能夠實例化ISession,實例化ISession后的對象能夠調用NHibernate下的數據庫操作方法。詳細他們之間怎么實例化,先上代碼。后面再來解釋。
? NHibernateDAO代碼例如以下,繼承INHibernateSessionFactory和實現IDAO父接口:
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Model; using IDAO; using NHibernate; using NHibernate.Criterion; using NHibernate.Linq; using Spring.Data.NHibernate.Support; using NHibernate.Cfg; using System.Text;namespace NHibernateDAO {[Spring.Stereotype.Repository]public class NHibernateDAO<T> : IDAO<T>{public ISessionFactory SessionFactory { get; set; }/// <summary>/// 獲取Session/// </summary>public ISession Session{get{return SessionFactory.GetCurrentSession();}}/// <summary>/// 當前實體相應的表名/// </summary>public string TableName{get { return typeof(T).ToString().Substring(typeof(T).ToString().LastIndexOf('.') + 1); }}/// <summary>/// 加入實體/// </summary>/// <param name="entity"></param>public int Add(T entity){using (ITransaction transaction = Session.BeginTransaction()){try{int id = (int)Session.Save(entity);Session.Flush();transaction.Commit();return id;}catch (HibernateException){transaction.Rollback();throw;}}}/// <summary>/// 改動實體/// </summary>/// <param name="entity"></param>public void Update(T entity){using (ITransaction transaction = Session.BeginTransaction()){try{Session.Update(entity);Session.Flush();transaction.Commit();}catch (HibernateException){transaction.Rollback();throw;}}}/// <summary>/// 保存或改動實體/// </summary>/// <param name="customer"></param>public void SaveOrUpdate(IList<T> list){using (ITransaction transaction = Session.BeginTransaction()){try{foreach (var entity in list){Session.SaveOrUpdate(entity);}Session.Flush();transaction.Commit();}catch (HibernateException){transaction.Rollback();throw;}}}/// <summary>/// 刪除實體/// </summary>/// <param name="entity"></param>public void Delete(T entity){using (ITransaction transaction = Session.BeginTransaction()){try{Session.Delete(entity);Session.Flush();transaction.Commit();}catch (HibernateException){transaction.Rollback();throw;}}}/// <summary>/// 按條件刪除/// </summary>/// <param name="sqlWhere">刪除條件</param>public void Delete(string sqlWhere){using (ITransaction transaction = Session.BeginTransaction()){try{Session.Delete(string.Format("from {0} Where {1}", TableName, sqlWhere));Session.Flush();transaction.Commit();}catch (HibernateException){transaction.Rollback();throw;}}}/// <summary>/// 依據ID得到實體/// </summary>/// <param name="id"></param>/// <returns></returns>public T Get(int id){return Session.Get<T>(id);}/// <summary>/// 依據ID得到實體/// </summary>/// <param name="id"></param>/// <returns></returns>public T Load(int id){return Session.Load<T>(id);}/// <summary>/// 得到全部實體/// </summary>/// <returns></returns>public IList<T> LoadAll(){return Session.Query<T>().ToList();}/// <summary>/// 按條件排序得到前N條記錄/// </summary>/// <param name="top">獲取條數</param>/// <param name="field">排序字段</param>/// <param order="field">排序方式。升序asc,降序desc</param>/// <returns></returns>public IList<T> QueryTop(int top, string field, string order){if (order == "asc"){return Session.CreateCriteria(typeof(T)).SetMaxResults(top).AddOrder(Order.Asc(field)).List<T>();}else{return Session.CreateCriteria(typeof(T)).SetMaxResults(top).AddOrder(Order.Desc(field)).List<T>();}}/// <summary>/// 依據條件得到實體/// </summary>/// <param name="sqlWhere">查詢條件</param>/// <returns></returns>public IList<T> Where(string sqlWhere){StringBuilder strSql = new StringBuilder(string.Format("from {0} c", TableName));if (!string.IsNullOrEmpty(sqlWhere)){strSql.Append(string.Format(" where {0}", sqlWhere));}return Session.CreateQuery(strSql.ToString()).List<T>();}/// <summary>/// 得到統計數量/// </summary>/// <param name="strWhere">查詢條件</param>/// <returns></returns>public int GetRecordCount(string sqlWhere){StringBuilder strSql = new StringBuilder(string.Format("select count(1) from {0} c", TableName));if (!string.IsNullOrEmpty(sqlWhere)){strSql.Append(string.Format(" where {0}", sqlWhere));}return (int)Session.CreateSQLQuery(strSql.ToString()).UniqueResult();}/// <summary>/// 分頁獲取數據列表/// </summary>/// <param name="PageSize">每頁獲取數據條數</param>/// <param name="PageIndex">當前頁是第幾頁</param>/// <param name="strWhere">查詢條件</param>/// <returns></returns>public IList<T> GetPageList(int PageSize, int PageIndex, string sqlWhere){StringBuilder strSql = new StringBuilder();strSql.Append(string.Format("select top {0} * from {1} where ID not in(select top ", PageSize,TableName));strSql.Append(PageSize * (PageIndex - 1));strSql.Append(string.Format(" ID from {0}", TableName));if (!string.IsNullOrEmpty(sqlWhere)){strSql.Append(string.Format(" where {0} ) and {0}", sqlWhere));}else{strSql.Append(")");}return Session.CreateSQLQuery(strSql.ToString()).AddEntity(typeof(T)).List<T>();}/// <summary>/// 依據數據字典父編碼和編碼獲取名稱/// </summary>/// <param name="parentNumber">父編碼</param>/// <param name="number">編碼</param>/// <returns></returns>public string GetName(string parentNumber, string number){string[] num = number.Split(',');List<string> list = new List<string>();list.AddRange(num);IQueryable<string> name = from q in Session.Query<T_Dictionary>()where q.ParentNumber == parentNumber && list.Contains(q.Number) orderby q.Numberselect q.Name;string nameStr = "";foreach (string n in name){nameStr += n + ",";}return nameStr.Contains(",") ? nameStr.Substring(0, nameStr.Length - 1) : nameStr;}/// <summary>/// 獲取該父編碼下最大編碼/// </summary>/// <param name="parentNumber">父編碼</param>/// <returns></returns>public int GetMaxNumber(string parentNumber){string strSql =string.Format("select case when MAX(cast(substring(Number,len(Number)-3,4) as int)) is null then 0 else MAX(cast(substring(Number,len(Number)-3,4) as int)) end from {0} where ParentNumber='{1}'",TableName, parentNumber);return ++Session.CreateQuery(strSql).List<int>()[0];}} }? 4. 加入一個數據庫訪問層實現類,以T_RoleDAO為例:
using System; using System.Collections; using IDAO; using Model;namespace NHibernateDAO {public class T_RoleDAO : NHibernateDAO<T_Role>, IT_RoleDAO{} }
? 相同滴。繼承NHibernateDAO并實現IT_RoleDAO接口。他便擁有了他們定義好的方法。假設有特殊方法代碼例如以下:
? 5. 以下,就來解釋一下他們都是怎么實例化的。
這里就用到Spring.NET依賴注入的方式實現,先看配置文件。在NHibernateDAO類庫下加入目錄Config,用來存放配置文件,然后加入一個命名為objects.xml的xml。這里必須定義每個數據庫訪問層對象,不能說他們都繼承NHibernateDAO,僅僅定義NHibernateDAO,這種話會報錯,由于后面BLL層要調用DAO層,他們之間是一一相應的。這里先簡單提一下,后面講到就明確了。代碼例如以下:
<?xml version="1.0" encoding="utf-8" ?> <objects xmlns="http://www.springframework.net"> <!--T_AreaDAO,管理T_Area的對象--> <object id="T_AreaDAO" type="NHibernateDAO.T_AreaDAO,NHibernateDAO"> <property name="SessionFactory" ref="NHibernateSessionFactory"/> </object> <!--T_AssessmentCoefficientDAO,管理T_AssessmentCoefficient的對象--> <object id="T_AssessmentCoefficientDAO" type="NHibernateDAO.T_AssessmentCoefficientDAO,NHibernateDAO"> <property name="SessionFactory" ref="NHibernateSessionFactory"/> </object> <!--T_AuthorityDAO,管理T_Authority的對象--> <object id="T_AuthorityDAO" type="NHibernateDAO.T_AuthorityDAO,NHibernateDAO"> <property name="SessionFactory" ref="NHibernateSessionFactory"/> </object> <!--T_ClientDAO,管理T_Client的對象--> <object id="T_ClientDAO" type="NHibernateDAO.T_ClientDAO,NHibernateDAO"> <property name="SessionFactory" ref="NHibernateSessionFactory"/> </object> <!--T_DictionaryDAO,管理T_Dictionary的對象--> <object id="T_DictionaryDAO" type="NHibernateDAO.T_DictionaryDAO,NHibernateDAO"> <property name="SessionFactory" ref="NHibernateSessionFactory"/> </object> <!--T_DrugDAO,管理T_Drug的對象--> <object id="T_DrugDAO" type="NHibernateDAO.T_DrugDAO,NHibernateDAO"> <property name="SessionFactory" ref="NHibernateSessionFactory"/> </object> <!--T_InvoicingCollectDetailDAO,管理T_InvoicingCollectDetail的對象--> <object id="T_InvoicingCollectDetailDAO" type="NHibernateDAO.T_InvoicingCollectDetailDAO,NHibernateDAO"> <property name="SessionFactory" ref="NHibernateSessionFactory"/> </object> <!--T_InvoicingDetailDAO,管理T_InvoicingDetail的對象--> <object id="T_InvoicingDetailDAO" type="NHibernateDAO.T_InvoicingDetailDAO,NHibernateDAO"> <property name="SessionFactory" ref="NHibernateSessionFactory"/> </object> <!--T_LogDAO,管理T_Log的對象--> <object id="T_LogDAO" type="NHibernateDAO.T_LogDAO,NHibernateDAO"> <property name="SessionFactory" ref="NHibernateSessionFactory"/> </object> <!--T_MenuDAO,管理T_Menu的對象--> <object id="T_MenuDAO" type="NHibernateDAO.T_MenuDAO,NHibernateDAO"> <property name="SessionFactory" ref="NHibernateSessionFactory"/> </object> <!--T_OpHistoryDAO,管理T_OpHistory的對象--> <object id="T_OpHistoryDAO" type="NHibernateDAO.T_OpHistoryDAO,NHibernateDAO"> <property name="SessionFactory" ref="NHibernateSessionFactory"/> </object> <!--T_RoleDAO,管理T_Role的對象--> <object id="T_RoleDAO" type="NHibernateDAO.T_RoleDAO,NHibernateDAO"> <property name="SessionFactory" ref="NHibernateSessionFactory"/> </object> <!--T_UserDAO,管理T_User的對象--> <object id="T_UserDAO" type="NHibernateDAO.T_UserDAO,NHibernateDAO"> <property name="SessionFactory" ref="NHibernateSessionFactory"/> </object> <!--V_InvoicingCollectDetailDAO,管理V_InvoicingCollectDetail的對象--> <object id="V_InvoicingCollectDetailDAO" type="NHibernateDAO.V_InvoicingCollectDetailDAO,NHibernateDAO"> <property name="SessionFactory" ref="NHibernateSessionFactory"/> </object> <!--V_InvoicingDetailDAO,管理V_InvoicingDetail的對象--> <object id="V_InvoicingDetailDAO" type="NHibernateDAO.V_InvoicingDetailDAO,NHibernateDAO"> <property name="SessionFactory" ref="NHibernateSessionFactory"/> </object> <!--V_TrackDAO,管理V_Track的對象--> <object id="V_TrackDAO" type="NHibernateDAO.V_TrackDAO,NHibernateDAO"> <property name="SessionFactory" ref="NHibernateSessionFactory"/> </object> <!--V_CoverageRateDAO,管理V_CoverageRate的對象--> <object id="V_CoverageRateDAO" type="NHibernateDAO.V_CoverageRateDAO,NHibernateDAO"> <property name="SessionFactory" ref="NHibernateSessionFactory"/> </object> <!--V_AssessDAO,管理V_Assess的對象--> <object id="V_AssessDAO" type="NHibernateDAO.V_AssessDAO,NHibernateDAO"> <property name="SessionFactory" ref="NHibernateSessionFactory"/> </object> <!--T_BuyDetailDAO,管理T_BuyDetail的對象--> <object id="T_BuyDetailDAO" type="NHibernateDAO.T_BuyDetailDAO,NHibernateDAO"> <property name="SessionFactory" ref="NHibernateSessionFactory"/> </object> </objects>
? 格式如上述代碼,先定義一個objects根節點,然后再objects中定義每個數據庫訪層,type指定“命名空間.類名,命名空間”,property指定屬性,name必須與NHibernateDAO中的SessionFactory同樣,因為每個數據庫訪問層都繼承了NHibernateDAO,全部他們就擁有了NHibernateDAO的屬性SessionFactory,ref指定SessionFactory實例化的對象,NHibernateSessionFactory是NHibernate框架封裝的數據庫訪問類。所以,我們看到我們沒有在代碼中實實例化SessionFactory。僅僅是定義了一個屬性,而是通過Spring.NET的配置文件來把SessionFactory實例化的,這就是所謂的依賴注入,也交控制反轉。
? 6. 細心的擼友能夠發現了,數據庫操作的類和方法我們定義好了,可是數據訪問的連接字符串還沒有,以下就來配置數據庫訪問文件。相同在NHibernateDAO的Config中加入DataAccess.xml,代碼例如以下:
<?xml version="1.0" encoding="utf-8" ?> <objects xmlns="http://www.springframework.net"xmlns:db="http://www.springframework.net/database"xmlns:tx="http://www.springframework.net/tx"><!--描寫敘述--><description>數據訪問的配置信息包括:DbProviderNHibernate</description><!-- 通過主應用程序的上下文配置文件引用 --><object type="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer, Spring.Core"><property name="ConfigSections" value="spring/databaseSettings"/></object><!-- 數據庫的配置 --><db:provider id="DbProvider"provider="SqlServer-2.0"connectionString="Data Source=${db.server};Database=${db.database};User ID=${db.userid} ;PassWord=${db.password}"/><!-- NHibernate 配置 --><!-- 能夠通過 name 為其指定別名 name="SessionFactory" --><object id="NHibernateSessionFactory"type="Spring.Data.NHibernate.LocalSessionFactoryObject,Spring.Data.NHibernate4"><!-- 關于數據庫連接的配置,直接使用 DbProvider 中的設置,這樣,不須要為 Hibernate 再提供連接串和驅動 --><property name="DbProvider" ref="DbProvider"/><!-- 包括有映射文件的程序集,須要分析的hbm程序集名稱 --><property name="MappingAssemblies"><list><value>Model</value></list></property><!-- 其它的參數 --><property name="HibernateProperties"><dictionary><!-- 方言 --><entry key="dialect" value="NHibernate.Dialect.MsSql2008Dialect"/><entry key="use_proxy_validator" value="false" /><entry key="show_sql" value="true"/></dictionary></property><!-- 必須添加此項說明,與 Spring 的聲明式事務集成 --><property name="ExposeTransactionAwareSessionFactory" value="true" /></object></objects>? 當中connectionString="Data Source=${db.server};Database=${db.database};User ID=${db.userid} ;PassWord=${db.password}中,我并沒有明白指定他們訪問地址、數據庫等。
這是一種類似定義一個變量的方式指定他們的訪問地址、數據庫等信息的,詳細變量的值是什么,會在后面web層的config配置文件里定義,按這個格式寫即可。先不用糾結。
這樣也方便維護。
? 最后,還是看一下NHibernateDAO層的文件夾結構:
轉載于:https://www.cnblogs.com/wzzkaifa/p/7295137.html
總結
以上是生活随笔為你收集整理的『Spring.NET+NHibernate+泛型』框架搭建之DAO(三)★的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDU 5741 Helter Skel
- 下一篇: Linux命令【第一篇】