>>>>>>
如果在整个应用内使用Hibernate,你可以把Hibernate放到App Server的CLASSPATH里面,自己写一个Singleton模式的SessionFactory,这样就行了。

Singleton在某些特殊的情况下可能会失效,所以你也可以把Hibernate配置到App Server的JNDI上,这需要在App Server刚启动的时候就运行Hibernate的初始化代码,详细的请见:http://www.jdon.com/jive/article.jsp?forum=16&thread=9188
<<<<<<

就是这一点,我不是太放心:就是何时hibernate 读取配置文件,得到 sessionFactory 的问题。如果直接在ejb中getConfigure(),显然违反
ejb规则,如果放到app server的jndi环境中,那就必然要改动 app server,这恐怕比较棘手。
再问一下,Singleton 模式会在什么情况下失效呢?如果Singleton 能解决
问题而又不违反ejb规范的话,那就比较理想了。

Robbin


如果只是在单个EJB里面使用Hibernate,可以把EJB和Hibernate打包在一起成EAR发布到App Server上,这样就行了。

<<<

这个方法可以吗?配置信息如何读取?还是在 ejb 发布的时候就一次性获得呢?还有就是那么多的mapping 文件何时读入?是否存在并发问题?

对 hibernate 架构不太熟悉,仅看了一下基本应用例程,请指教。

谢谢

>> 不知道大家对Hibernate 和 jdo2.0 有什么看法?

JDO2.0还不知道猴年马月才出来,关于JDO1.0,我前面有一个帖子详细谈了JDO的重大缺陷。

从理论上来说,Singleton模式是不会有问题的。因为用Singleton获得SessionFactory是用App Server Class Loader来load,而EJB Class Loader和Web app Class Loader都是继承自App Server Class Loader,它们向上搜索的时候,会找到同一个SessionFactory实例,而不会出现找到不同SessionFactory对象实例的情况。我之所以说Singleton在某些特殊的情况下可能会失效,是因为我没有在所有的App Server试过一遍而已,所以不敢肯定是否会有例外出现,在Weblogic上是绝无问题的。不管怎么说,我还是推荐使用这种方法,不但简单,而且速度最快,并且对所有的App Server来说配置方法都一样。其实,就算出现例外也没有什么大不了的,最多就是Hibernate多初始化几次而已,不用放在心上。

使用JNDI是一个很正统的做法,把所有的App Server的资源都配置到JNDI树上去查找,有利于资源的统一管理和查找。JNDI的绑定是Hibernate在初始化过程中完成的,其实也不需要自己写什么代码,你要怕改动App Server的设置,那也很简单,每次启动App Server之后,你先手工访问一个JSP页面,这个JSP页面里面进行Hibernate的初始化,这样就OK了,JNDI会自动绑定好的。

仅在单个EJB中使用Hibernate,其实就是用EJB Class Loader去load Hibernate,你可以在EJB setSessionContext方法里面对Hibernate进行初始化,不存在并发问题。

>>>>>
使用JNDI是一个很正统的做法,把所有的App Server的资源都配置到JNDI树上去查找,有利于资源的统一管理和查找。JNDI的绑定是Hibernate在初始化过程中完成的,其实也不需要自己写什么代码,你要怕改动App Server的设置,那也很简单,每次启动App Server之后,你先手工访问一个JSP页面,这个JSP页面里面进行Hibernate的初始化,这样就OK了,JNDI会自动绑定好的。

仅在单个EJB中使用Hibernate,其实就是用EJB Class Loader去load Hibernate,你可以在EJB setSessionContext方法里面对Hibernate进行初始化,不存在并发问题。
<<<<<<

谢谢回复!
如果使用 Tomcat 类的服务器的话,用Singleton 是最理想的方法了(其实也是必须的办法),但在 ejb 中,我仍然比较狐疑,EJB 规范允许这样做吗?
更要命的是 hibernate 初始化文件中包含了大量的 mapping 文件指向。
初始化时会不会有问题?mapping 文件放在哪里?
(在tomcat下测试时,mapping 文件是在运行时读入的?但在EJB下,这些工作应当在部署时完成,是这样吗?)

我总觉得这些东东必须交由容器来管理才能保证tp monitor 的正常工作,也就是必须要合并到容器的资源管理和部署管理中去才行。

pls.....

>>但在 ejb 中,我仍然比较狐疑,EJB 规范允许这样做吗?<<

不是在EJB Class Loader级别用Singleton,在这个级别用Singleton肯定会失效。是在App Server Class Loader级别用Singleton。这个级别的class是由JDK App Class Loader负载load class,生成的object实例直接由JVM来管理,而不是由App Server管理的,所以不会出现失效。别太拘泥于规范,具体问题具体分析,搞清楚原理比背什么规范有用的多。

>>更要命的是 hibernate 初始化文件中包含了大量的 mapping 文件指向。
初始化时会不会有问题?mapping 文件放在哪里?<<

你该不会连mapping文件放在哪里都不知道吧?

>>在tomcat下测试时,mapping 文件是在运行时读入的?但在EJB下,这些工作应当在部署时完成,是这样吗?<<

不管在哪里,都是在Hibernate初始化的过程中读入的,没有区别。

>>我总觉得这些东东必须交由容器来管理才能保证tp monitor 的正常工作,也就是必须要合并到容器的资源管理和部署管理中去才行。<<

我还是那句话,搞清楚原理比什么都重要。Hibernate本身不是一种资源,它不过是一些封装代码而已,那么Hibernate下面什么才是真正的资源呢?是数据库连接池!所以Hibernate一定要使用App Server的数据库连接池才能保证容器事务管理功能。至于Hibernate本身,根本无关紧要,就算把Hibernate配置到JNDI上也不过是预先创建好了SessionFactoryImpl对象,省得运行的时候再创建罢了。

Thank u.
我再研究研究hibernate的初始化过程。

但是这个办法
>>
如果只是在单个EJB里面使用Hibernate,可以把EJB和Hibernate打包在一起成EAR发布到App Server上,这样就行了。
<<
看来肯定是不行的。

如果你实在不理解,读读源代码会对你有很大的帮助。不过话说回来,我觉得一个人的Java基础也很重要,Java基础打得好,学习什么都不觉得困难,都能举一反三,就算碰到问题也能自己解决;相反,基础不好学什么都会困难重重。而打好Java基础的最根本的点在于理解JVM的内存分配原理和JVMload class的原理,只要把这两点真正彻底的理解了,不管碰到什么问题都会迎刃而解,至少我自己就是这样的,碰到了难以解决的问题,把这两个基本原理运用上分析一下,就无往而不利。

1、JVM内存分配原理

JVM的内存分配原理主要搞清楚JVM的内存结构,以及栈内存和堆内存是如何进行分配的,字节码是如何运行的,这方面内容前面一个讨论static方法帖子我说过的。

2、JVM的Class Loader

王森的那本《Java深度历险》详细的分析过了,不管他只分析了JDK的Class Loader层次,没有分析App Server的Class Loader层次。其实只要留意一下我贴过的帖子,就会发现Class Loader一定是我提到次数最多的内容了,因为它实在太有用了。就是这个在App Server上配置Hibernate的问题,归根结底,还是会落到Class Loader上来。

EJB 的规范中不允许有I/O操作,所以我的问题很简单:就是在 ejb 中采用什么样的技巧,去绕过配置文件读取这个问题?这和 classload 有关系吗?

你对EJB规范的理解出了偏差!

EJB规范说的是不应该在EJB里面使用IO,而且事实上也的确如此,更精确的来说是EJB Class Loader级别不能读写外部配置文件。

如果把EJB和Hibernate打包成EAR发布,实际上Hibernate里面的配置文件是EJB的一部分,在EAR的deploy过程中被EJB Class Loader load进入内存,在EJB的执行过程,并没有外部IO操作,而是纯粹内存操作。

如果把Hibernate配置到App Server的CLASSPATH里面,使用Singleton或者JNDI来获得SessionFactory的话,那么并没有EJB的IO过程。在EJB的执行过程中,EJB Class Loader找不到Hibernate,向上找,交给App Class Loader去找,而App Class Loader找到Hibernate,并且读入Hibernate配置文件。这并不是EJB本身的IO。

Robbin,

我可以补充两句吗?

打包成EJB jar文件的方式比JNDI方式灵活,因为EJB jar 方式可以配置不同的Map文件,也就是不同的map文件可以指向不同的数据库,也可以有不同的配置。不好的地方就是配置复杂占用空间。JNDI方式简单且容易管理。 不过上面我所说,并没有考虑集群的情况,也许有了集群,EJB jar文件方式也同样灵活,不太清楚。

那你也可以配置好几个JNDI,指向不同的数据库。

谢谢guty,

我想我搞清楚cglib和Dynamic proxy还要假以时日。

我的理解是这样的:

Hibernate的类库与配置文件是放在同一个classloader级别的,如果使用JNDI方式,类库放在App classloader这一级,那么就只有一个Hibernate配置文件放在App的classpath中。读Hibernate文档, 没有看见可以在指定读取的配置文件。

Robbin, 我想我是明白你的意思了。

你可能是指一台机跑两个weblogic,这样就可以指定不同的JNDI了。希望没有误解。