首页
最近更新
热门教程
ASP.NET
开发语言
开发环境
AJax教程
控件开发
统计报表
数据库
Web服务
安装部署
HTML教程
Javascript
XML教程
Community Server
NHibernate
书籍推荐
常用工具
实用代码
教程全文搜索
首页
>>
NHibernate
NHibernate的Session管理
添加人:
iyond
添加时间:2007-04-10 阅读次数:2890
收藏此教程
看过hibernate文档的人应该看到在“
第 1 章 在Tomcat中快速上手
”,可以看到代码中使用ThreadLocal作为Session的存放容器。
public
static
final
ThreadLocal session
=
new
ThreadLocal();
查看
JDK的文档
,这个东东作用是给每个线程提供单独的静态变量,在一个线程内部共享,而不同的线程间不共享。
在hibernate中Session 是“单线程”的,即多个线程访问一个Session 会出问题。所以在最普遍的做法是一个操作就创建一个新的Session。Session对应着一个数据库的连接,而且Session内部提供了缓存(一级缓存)的机制。这样做意味这更多的数据库连接次数和缓存资源的浪费。
hibernate中使用使用ThreadLocal的目的就是让Session在一个线程内共享,尽可能的较少连接数据库的次数和尽可能的使用到一级缓存。
对于NHibernate是否有实现的办法呢。我们找到了
ThreadStaticAttribute
,它指示静态字段的值对于每个线程都是唯一的。用法如下
[ThreadStatic]
static
int
value;
似乎这样就可以了。在WinFrom,控制台应用程序和类库等中的确是没有问题了。但在Asp.Net中问题可不这么简单。在Java里Jsp作为Servlet来运行,是单线程的。而Asp.Net就不一样了,他用到了多个线程,造成的情况是:"当有多个线程的时候,ThreadStaticAttribute的变量被第一个线程初始化后,其它的线程访问到的都是null,而每个HttpRequest则可能有多个线程为其服务,因而有人称ThreadStatic is evil。"(此段引用
在ASP.NET中使用NHibernate - 风满袖 - 博客园
)。所以我们好的做法是使用HttpContext.Current.Items来共享session。使用HttpModule来处理之。在“
在ASP.NET中使用NHibernate - 风满袖 - 博客园
”里已经做了讲解。
我的想法是做一个统一的ISession提供者,只需要简单的配置即可用在不同的应用程序里。
储存ISession类需要实现的接口。
/**/
/*
* 修改日期:2005-10-05
* 修改人:DDL
* 修改原因:
*
*/
using
NHibernate;
namespace
Index.Data.NHibernateSessionStorage
{
/**/
///
<summary>
///
储存一个ISession
///
</summary>
public
interface
ISessionStorage
{
/**/
///
<summary>
///
获得ISession
///
</summary>
///
<returns></returns>
ISession Get();
/**/
///
<summary>
///
保存ISession
///
</summary>
///
<param name="value"></param>
void
Set(ISession value);
}
}
非Asp.Net程序使用的ISession提供者
/**/
/*
* 修改日期:2005-10-10
* 修改人:DDL
* 修改原因:
*
*/
using
System;
using
NHibernate;
namespace
Index.Data.NHibernateSessionStorage
{
/**/
///
<summary>
///
保存一个Session在一个thread-static的类成员中。
///
</summary>
public
class
ThreadSessionSource : ISessionStorage
{
[ThreadStatic]
private
static
ISession m_Session;
/**/
///
<summary>
///
获得Session
///
</summary>
///
<returns></returns>
public
ISession Get()
{
if
(m_Session
!=
null
)
{
if
(
!
m_Session.IsConnected)
{
m_Session.Reconnect();
}
}
return
m_Session;
}
/**/
///
<summary>
///
保存Session
///
</summary>
///
<param name="value"></param>
public
void
Set(ISession value)
{
if
(value.IsConnected)
{
value.Disconnect();
}
m_Session
=
value;
}
}
}
Asp.Net程序使用的ISession提供者
/**/
/*
* 修改日期:2005-10-05
* 修改人:DDL
* 修改原因:
*
*/
using
NHibernate;
using
System.Web;
using
Index.Data.NHibernateSessionStorage.CFG;
namespace
Index.Data.NHibernateSessionStorage
{
/**/
///
<summary>
///
储存一个ISession
<see cref="HttpContext.Items" />
集合.
///
</summary>
public
class
HttpSessionSource : ISessionStorage
{
/**/
///
<summary>
///
获得ISession
///
</summary>
///
<returns>
获得的ISession
</returns>
public
ISession Get()
{
return
(ISession)HttpContext.Current.Items[Config.HttpSessionSourceItemName];
}
/**/
///
<summary>
///
保存ISession
///
</summary>
///
<param name="value">
需要保存的ISession
</param>
public
void
Set(ISession value)
{
if
(value
!=
null
)
{
HttpContext.Current.Items.Add(Config.HttpSessionSourceItemName, value);
}
else
{
HttpContext.Current.Items.Remove(Config.HttpSessionSourceItemName);
}
}
}
}
通过读取配置文件让工厂提供不同的ISession提供者
/**/
/*
* 修改日期:2005-10-05
* 修改人:DDL
* 修改原因:
*
*/
using
System;
using
Index.Data.NHibernateSessionStorage.CFG;
namespace
Index.Data.NHibernateSessionStorage
{
/**/
///
<summary>
///
产生ISessionStorage的工厂
///
</summary>
public
class
ISessionStorageFactory
{
/**/
///
<summary>
///
获得ISessionStorage
///
</summary>
///
<returns></returns>
public
static
ISessionStorage GetSessionStorage()
{
if
(Config.SessionSourceType
==
"
http
"
)
//
使用
{
return
new
HttpSessionSource();
}
else
if
(Config.SessionSourceType
==
"
threadStatic
"
)
{
return
new
ThreadSessionSource();
}
else
{
throw
new
NotSupportedException(
"
不支持的SessionSourceType!
"
+
Config.SessionSourceType);
}
}
}
}
配置类
/**/
/*
* 修改日期:2005-10-05
* 修改人:DDL
* 修改原因:
*
*/
using
System;
using
System.Configuration;
namespace
Index.Data.NHibernateSessionStorage.CFG
{
/**/
///
<summary>
///
配置信息帮助类
///
</summary>
public
class
Config
{
私有成员
#region
私有成员
private
static
object
m_Locker
=
new
object
();
private
static
string
m_SessionSourceType
=
String.Empty;
private
static
string
m_HttpSessionSourceItemName
=
String.Empty;
#endregion
属性
#region
属性
/**/
///
<summary>
///
Session资源源类型;http,threadStatic
///
</summary>
public
static
string
SessionSourceType
{
get
{
lock
( m_Locker )
{
if
(m_SessionSourceType
==
String.Empty)
{
return
ConfigurationManager.AppSettings[
"
SessionSourceType
"
];
}
else
{
return
m_SessionSourceType;
}
}
}
}
/**/
///
<summary>
///
HttpSessionSource存放HttpContext.Current.Items的键值名
///
</summary>
public
static
string
HttpSessionSourceItemName
{
get
{
lock
( m_Locker )
{
if
(m_HttpSessionSourceItemName
==
String.Empty)
{
return
ConfigurationManager.AppSettings[
"
HttpSessionSourceItemName
"
];
}
else
{
return
m_HttpSessionSourceItemName;
}
}
}
}
/**/
///
<summary>
///
是否使用Session资源源
///
</summary>
public
static
bool
UserSessionSource
{
get
{
lock
(m_Locker)
{
return
Convert.ToBoolean(ConfigurationManager.AppSettings[
"
UserSessionSource
"
]);
}
}
}
#endregion
}
}
然后进行其他的一些封装操作
/**/
/*
* 修改日期:2005-10-05
* 修改人:DDL
* 修改原因:生成工厂类
*
*/
using
Index.Data.NHibernateSessionStorage.CFG;
using
NHibernate;
using
NHibernate.Cfg;
namespace
Index.Data.NHibernateSessionStorage
{