帐本子

二手代码贩子
posts - 18, comments - 52, trackbacks - 0, articles - 0

nHibernate学习小结及代理模板

Posted on 2008-07-11 15:00 莫耶 阅读(1480) 评论(8)  编辑 收藏 网摘
  近日为学习Spring.net,开始上手nHibernate,其间遇到不少问题,但也小有收获,毕竟学习新框架是有曲线的

  现小结一下,算是汇报:

  1、关于配置文件
  在web项目中,大部分的配置都是在web.config中进行部署,这样的好处是整合了各种应用的配置,维护比较集中。
  由于使用的nHibernate为1.2.1GA,故而它对应的urn(统一资源名称,Uniform Resource Name, URN)为:“nhibernate-configuration-2.2”,这个常识性问题曾经困扰了我很久,运行时经常出现的异常诸如“not found section:'session-factory'”,其实是由于使用CodeSmith生成的模板文件(hbm.xml)中声明的urn为“nhibernate-configuration-2.0”所致。
  在web.config中,进行这样的配置,是正确的:

  <configSections>
    
<section
            
name="hibernate-configuration"
            type
="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />
  
</configSections>
  
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    
<session-factory xmlns="urn:nhibernate-configuration-2.2">
      
<property name="hibernate.connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
      
<property name="hibernate.connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
      
<property name="hibernate.connection.connection_string">Server=Locke.mo;database=woodigg;User Id=locke;Password=locke</property>
      
<property name="hibernate.dialect">NHibernate.Dialect.MsSql2000Dialect</property>
      
<property name="show_sql">false</property>
      
<property name="use_proxy_validator">false</property>
      
<property name="use_outer_join">true</property>
    
</session-factory>
  
</hibernate-configuration>

  2、使用Session的Load方法获取的对象只是个代理对象!
  这意味着这个对象,你只能在Session的生命周期内使用它,一旦Session关闭,此对象也终止服务,如果此后试图访问它,将抛出“Exception initializing proxy”异常。
  因为,在整个Session范围内,应用程序没有访问过这个代理类对象,那么代理类的实例一直不会被初始化,Hibernate不会执行任何select语句。(来自JavaEye)
  我的解决办法是,强制其实例化:     
  //在Session范围内显式初始化代理类实例
  if (!NHibernateUtil.IsInitialized(t))
    NHibernateUtil.Initialize(t);

  3、在《Spring in Action》一书中,作者提到Spring和其他数据持久化框架集成时,都提供了强大的模板类(如JdbcTemplate、HibernateTemplate等),真是令人羡慕的功能,毕竟大部分的DAO类里有着很多重复繁冗的代码,而这80%的代码其实是与具体业务无关的!
   既然现在还未到集成Spring.Net的地步,那就先为nHibernate单独实现一个模板吧:

  
using System;
using System.Collections.Generic;
using System.Text;
using NHibernate;
using log4net;

namespace woodigg.DAO
{
    
/// <summary>
    
/// 增删改模板
    
/// </summary>

    public class HibernateTemplate
    
{
        
/// <summary>
        
/// 泛型读取
        
/// </summary>
        
/// <param name="obj"></param>
        
/// <param name="id"></param>

        public static T LoadFromId<T>(object id)
        
{
            ISession session 
= Sessions.GetSession();
            
try
            
{
                T t 
= session.Load<T>(id);
                
//在Session范围内显式初始化代理类实例
                if (!NHibernateUtil.IsInitialized(t))
                    NHibernateUtil.Initialize(t);
                
return t;
            }

            
catch (Exception ex)
            
{
                ILog log 
= LogManager.GetLogger(typeof(HibernateTemplate));
                log.Error(ex.Message, ex);
                
return default(T);
            }

            
finally
            
{
                session.Close();
            }

        }


        
/// <summary>
        
/// 存
        
/// </summary>
        
/// <param name="obj"></param>

        public static bool Save(object obj)
        
{
            ISession session 
= Sessions.GetSession();
            ITransaction trans 
= null;
            
try
            
{
                trans 
= session.BeginTransaction();
                session.Save(obj);
                trans.Commit();
                
return true;
            }

            
catch (Exception ex)
            
{
                ILog log 
= LogManager.GetLogger(typeof(HibernateTemplate));
                log.Error(ex.Message, ex);
                trans.Rollback();
                
return false;
            }

            
finally
            
{
                session.Close();
            }

        }


        
/// <summary>
        
/// 更新
        
/// </summary>
        
/// <param name="obj"></param>

        public static bool Update(object obj)
        
{
            ISession session 
= Sessions.GetSession();
            ITransaction trans 
= null;
            
try
            
{
                trans 
= session.BeginTransaction();
                session.Update(obj);
                trans.Commit();
                
return true;
            }

            
catch (Exception ex)
            
{
                ILog log 
= LogManager.GetLogger(typeof(HibernateTemplate));
                log.Error(ex.Message, ex);
                trans.Rollback();
                
return false;
            }

            
finally
            
{
                session.Close();
            }

        }


        
/// <summary>
        
/// 删
        
/// </summary>
        
/// <param name="obj"></param>

        public static bool Delete(object obj)
        
{
            ISession session 
= Sessions.GetSession();
            ITransaction trans 
= null;
            
try
            
{
                trans 
= session.BeginTransaction();
                session.Delete(obj);
                trans.Commit();
                
return true;
            }

            
catch (Exception ex)
            
{
                ILog log 
= LogManager.GetLogger(typeof(HibernateTemplate));
                log.Error(ex.Message, ex);
                trans.Rollback();
                
return false;
            }

            
finally
            
{
                session.Close();
            }

        }


        
/// <summary>
        
/// 查询
        
/// </summary>
        
/// <param name="obj"></param>

        public static IList<T> Seek<T>(string where)
        
{
            ISession session 
= Sessions.GetSession();
            
try
            
{
                
//模板反射
                T obj = (T)System.Reflection.Assembly.GetAssembly(typeof(T)).CreateInstance(typeof(T).ToString());

                
string hql = string.Format("from {0} {1}",
                    obj.GetType().ToString(),
                    
where.ToUpper().StartsWith("WHERE"? where : "WHERE " + where);

                IQuery query 
= session.CreateQuery(hql);

                IList
<T> list = query.List<T>();
                
return list;
            }

            
catch (Exception ex)
            
{
                ILog log 
= LogManager.GetLogger(typeof(HibernateTemplate));
                log.Error(ex.Message, ex);
                
return null;
            }

            
finally
            
{
                session.Close();
            }

        }

    }

}


  差点忘了,它用到的SessionFactory:
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using NHibernate;
using NHibernate.Cfg;

namespace woodigg.DAO
{
    
public class Sessions
    
{
        
private static readonly object lockObj = new object();          // 用于singleton模式进行锁定
        private static ISessionFactory _factory;                        // sesssion 工厂

        
public Sessions()
        
{
        }


        
/// <summary>
        
/// 单一静态工厂
        
/// </summary>

        public static ISessionFactory Factory
        
{
            
get {
                
if (_factory == null)
                
{
                    
lock (lockObj)          // 保证线程安全
                    {
                        
if (_factory == null)
                        
{
                            
// 查找hibernate.cfg.xml
                            Configuration cfg = new Configuration().Configure();
                            
// 不需要mapping,直接获取当前运行程序集
                            cfg.AddAssembly(Assembly.GetExecutingAssembly());
                            _factory 
= cfg.BuildSessionFactory();
                        }

                    }

                }

                
return _factory;
            }

        }


        
/// <summary>
        
/// 打开一个会话连接
        
/// </summary>
        
/// <returns></returns>

        public static ISession GetSession()
        
{
            
return Factory.OpenSession();
        }

    }

}

Feedback

#1楼    回复  引用  查看    

2008-07-11 15:02 by Selfocus      
好,学习学习!

#2楼    回复  引用  查看    

2008-07-11 16:34 by kiler      
推荐使用SessionFactory的GetCurrentSession()来获取session,这样来说可以更方便的管理Session的生命周期,可以通过设置hibernate.current_session_context_class来定义如何管理Session的生命周期。

#3楼    回复  引用  查看    

2008-07-11 18:30 by wind.hong      
楼主可以把背景音乐关了么?呵呵,感觉会比较安静,小小建议 :)

#4楼    回复  引用  查看    

2008-07-11 20:52 by Klesh Wong      
实体类返回后session即被关闭,那,LazyLoad会用不了吧?
好像还是直接用ISession好吧。

#5楼    回复  引用    

2008-07-12 13:37 by adfadsfadfadfa [未注册用户]
d楼主可以把背景音乐关了么?呵呵,感觉会比较安静,小小建议 :)

#6楼    回复  引用  查看    

2008-07-12 13:49 by kanne      
帮我关下背景音乐嘛?

#7楼 [楼主]   回复  引用  查看    

2008-07-12 14:19 by 莫耶      
应广大观众强烈要求
将扰人的背景音乐进行了关闭
期限是一万年

#8楼 [楼主]   回复  引用  查看    

2008-07-12 14:22 by 莫耶      
@kiler

对,你说的很有道理
正在进一步研究中
session的生命周期管理
才是应用nHibernate的关键