DDLLY命名空间
DDLLY命名空间有两个类DDL和LLY
博客园
|
首页
| |
发新文章
|
联系
|
订阅
|
管理
NHibernate的Session管理
代码下载
看过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
{
/**/
///
<summary>
///
用来生成ISession实例的工厂
///
</summary>
public
static
class
NHibernateDatabaseFactory
{
私有静态变量
#region
私有静态变量
private
static
object
m_Locker
=
new
object
();
private
static
Configuration m_Configuration
=
null
;
private
static
ISessionFactory m_SessionFactory
=
null
;
private
static
ISessionStorage m_Sessionsource;
#endregion
静态构造函数
#region
静态构造函数
static
NHibernateDatabaseFactory()
{
m_Sessionsource
=
ISessionStorageFactory.GetSessionStorage();
}
#endregion
内部静态变量
#region
内部静态变量
/**/
///
<summary>
///
NHibernate配置对象
///
</summary>
public
static
Configuration Configuration
{
get
{
lock
(m_Locker)
{
if
(m_Configuration
==
null
)
{
CreateConfiguration();
}
return
m_Configuration;
}
}
set
{ m_Configuration
=
value; }
}
/**/
///
<summary>
///
NHibernate的对象工厂
///
</summary>
internal
static
ISessionFactory SessionFactory
{
get
{
if
(
null
==
m_SessionFactory)
{
if
(m_Configuration
==
null
)
{
CreateConfiguration();
}
lock
(m_Locker)
{
m_SessionFactory
=
Configuration.BuildSessionFactory();
}
}
return
m_SessionFactory;
}
}
#endregion
公共方法
#region
公共方法
/**/
///
<summary>
///
建立ISessionFactory的实例
///
</summary>
///
<returns></returns>
public
static
ISession CreateSession()
{
if
(Config.UserSessionSource)
//
如果使用保存的ISession
{
ISession s
=
m_Sessionsource.Get();
if
(s
==
null
)
{
s
=
SessionFactory.OpenSession();
m_Sessionsource.Set(s);
}
return
s;
}
else
//
如果使用新ISession
{
return
SessionFactory.OpenSession();
}
}
#endregion
私有方法
#region
私有方法
private
static
void
CreateConfiguration()
{
m_Configuration
=
new
Configuration();
//
Add interceptor, if you need to.
//
_config.Interceptor = new Interceptor();
}
#endregion
}
}
使用方法
非Asp.net应用配置
<
appSettings
>
<
add
key
="SessionSourceType"
value
="threadStatic"
/>
<
add
key
="HttpSessionSourceItemName"
value
="NHSession"
/>
<
add
key
="UserSessionSource"
value
="true"
/>
</
appSettings
>
Asp.net应用配置
<
appSettings
>
<
add
key
="SessionSourceType"
value
="http"
/>
<
add
key
="HttpSessionSourceItemName"
value
="NHSession"
/>
<
add
key
="UserSessionSource"
value
="true"
/>
</
appSettings
>
<
httpModules
>
<
add
type
="Index.Data.NHibernateData.SessionStorage.NHSessionModule, Index.Data.NHibernate"
name
="NHSessionModule"
/>
</
httpModules
>
然后在程序开始的时候配置下
Index.Data.NHibernateData.SessionStorage.NHibernateFactory.Configuration.Configure(Server.MapPath(
"
~
"
)
+
"
\\hibernate.cfg.xml
"
);
对于Asp.net我会把次段代码写在Global.asax的Application_Start方法里。
绿色通道:
好文要顶
关注我
收藏该文
与我联系
发表于 2006-08-04 13:32
DDL
阅读(5869)
评论(15)
编辑
收藏
评论
1702476
#1楼
把你写的关于NHibernate的文章整理一下放在一篇文章里面做链接,并进行分类,这样可以收录到精华区:-)
#2楼
[
楼主
]
@TerryLee
我可能还会有十篇左右关于NHibernate的文章,等全部写完我会整理出一个目录,但这个过程可能会比较长,我尽量做到每周坚持一篇,所以暂时只能写一篇放一篇.
#3楼
@DDL
好的,支持!
#4楼
写得不错,支持一下
#5楼
支持!
另外在nh主页上有一个连接:
http://blogs.intesoft.net/simon/articles/16.aspx
里面Simon Green也提供了一种做法,也是使用httpmodule来管理session(看来这已经成为了一种共识),我觉得更简洁一些,并且我把它用在实际项目中,运行良好。
#6楼
支持
学习中...
#7楼
[
楼主
]
@蔡克伦
http://blogs.intesoft.net/simon/articles/16.aspx
里面的Session管理和在Asp.net中我写的其实是一样的,而我还考虑到了非Winfrom和其他的应用程序.
我单独把这块提出来,因为可以在他上面写数据访问的帮助类库.
#8楼
是不是这样使用了就不用再每次操作都不会再关系Session的关闭问题了?
而且我在使用的过程中发现一个问题,NHibernateDatabaseFactory.CreateSession()有时候获取到的Session是已经关闭了的,所以最好给它加上
if (!s.IsConnected)
s.Reconnect();
#9楼
[
楼主
]
@杨炎武
在我调用此类库的其他类库中,对此进行了其他的处理,所以我使用时不存在此问题.
至于你说的问题,你可以按你的想法进行更改.
#10楼
Castle的NHibernateIntegration已经解决的这个问题,而且功能更加丰富。不过它依赖于IOC。如果不用IOC,还得改写。
#11楼
@DDL
你的ThreadSessionSource 中的set()
if (value.IsConnected)
{
value.Disconnect();
}
为什么要把session断开连接再保存?
如果windows程序下,
我第一次在打开新session后需要保存而调用set
岂不是connection在不知情的情况下被断开?
ISession s = m_Sessionsource.Get();
if (s == null)
{
s = SessionFactory.OpenSession();
m_Sessionsource.Set(s);
}
这么做是否是出于别的考虑?
#12楼
学习
#13楼
对于有多个数据库连接的情况是不是不适用
#14楼
--引用--------------------------------------------------
ivanking: @DDL
<br>你的ThreadSessionSource 中的set()
<br> if (value.IsConnected)
<br> {
<br> value.Disconnect();
<br> }
<br>为什么要把session断开连接再保存?
<br>如果windows程序下,
<br>我第一次在打开新session后需要保存而调用set
<br>岂不是connection在不知情的情况下被断开?
<br>
<br> ISession s = m_Sessionsource.Get();
<br> if (s == null)
<br> {
<br> s = SessionFactory.OpenSession();
<br>
<br> m_Sessionsource.Set(s);
<br> }
<br>这么做是否是出于别的考虑?
--------------------------------------------------------
他这样写的话,好处在于能控制数据库的链接资源。
在一个Session中多查询,多删除,处理时。可以只连一次,处理完后释放资源。
可见的资源管理,这样倒是很好。。。
不知道作者是不是这种意图。
#15楼
m_HttpSessionSourceItemName
这个值我发现一直是空的
注册用户登录后才能发表评论,请
登录
或
注册
,
返回博客园首页
。
首页
博问
闪存
新闻
园子
招聘
知识库
最新IT新闻
:
·
美国空军拟最多购买1.8万台iPad 2
·
伊朗封杀Gmail和Facebook等互联网服务
·
分析称专利之争让谷歌苹果两败俱伤
·
Android平台发现新型手机病毒Rootsmart
·
HTC首款Android4.0手机大曝光
»
更多新闻...
最新知识库文章
:
·
高级编程语言的发展历程
·
如何学习一门新的编程语言?
·
学习不同编程语言的重要性
·
为什么我喜欢富于表达性的编程语言
·
计算机专业的女生为什么要学编程
»
更多知识库文章...
China-pub 2011秋季教材巡展
China-Pub 计算机绝版图书按需印刷服务
随笔:81 文章:0 评论:963 引用:56
<
2006年8月
>
日
一
二
三
四
五
六
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
公告
只有偏执狂才能生存。
教堂尖项上的风标,即使由钢铁制成,如果不懂得顺应风势的艺术,一样会被暴风立即摧毁。
 
原创
技术文章,
转载
请注明来源。
昵称:
DDL
园龄:
7年8个月
粉丝:
20
关注:
4
搜索
常用链接
我的随笔
我的评论
我的参与
最新评论
我的标签
随笔分类
(88)
.NET(11)
(rss)
Asp.net(5)
(rss)
NHibernate(29)
(rss)
Office编程(1)
(rss)
Python(2)
(rss)
VIM(1)
(rss)
XML
(rss)
编程其他(1)
(rss)
代码生成(4)
(rss)
读书笔记(6)
(rss)
规范文档(1)
(rss)
设计(架构)模式(2)
(rss)
思考和感悟(4)
(rss)
随便写写(17)
(rss)
团队管理(2)
(rss)
正则表达式(2)
(rss)
project
patterns & practices Application Architecture Guide
友情博客
eric_gqs
Ike
Robin's Space
SHY520
(rss)
Terrylee
(rss)
林子
(rss)
积分与排名
积分 - 281066
排名 - 253
最新评论
阅读排行榜
评论排行榜
推荐排行榜