博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring对HibernateSession的管理之封装SessionFactory
阅读量:4921 次
发布时间:2019-06-11

本文共 7481 字,大约阅读时间需要 24 分钟。

  我刚刚在上一篇博文中将Spring对HibernateSession的管理做了一些皮毛的分析,主要围绕着Spring是怎样平衡Session的关闭时间。即在是否需要延时Session有效期以保证页面的调用。

  

  那么现在我们来看看Spring是怎样管理Session的生产者:SessionFactory的。

  首先,我们在学习Spring的时候一般都会涉及到将SSH框架整合起来使用了,还记得我们怎样配置Spring吗?

1 
2
7 8 …… 9
11
13
14
16
17
18
19
20
22
23
24
25
26
27
28 org.hibernate.dialect.Oracle10gDialect29
30
update
31
32
33
34
orm/Users.hbm.xml
35
36
37 38
39
40
41
42
43
44
45
46
47 ……48

  在不涉及到声明性事务和自动装配时我们一般按上述配置(上述配置为MyEclipse环境下的自动生成)。

  不知道大家有没有注意到:我们的Dao需要的SessionFactory是org.hibernate.SessionFactory(我们的Dao为了代码重用,继承自HibernateDaoSupport),而上面的装配却没有给一个SessionFactory或其子类。

  

  org.springframework.orm.hibernate3.support.HibernateDaoSupport源代码(省略了注释):

1 package org.springframework.orm.hibernate3.support; 2  3 import org.hibernate.HibernateException; 4 import org.hibernate.Session; 5 import org.hibernate.SessionFactory; 6  7 import org.springframework.dao.DataAccessException; 8 import org.springframework.dao.DataAccessResourceFailureException; 9 import org.springframework.dao.support.DaoSupport;10 import org.springframework.orm.hibernate3.HibernateTemplate;11 import org.springframework.orm.hibernate3.SessionFactoryUtils;12 public abstract class HibernateDaoSupport extends DaoSupport {13 14     private HibernateTemplate hibernateTemplate;15 16     public final void setSessionFactory(SessionFactory sessionFactory) {17         if (this.hibernateTemplate == null || sessionFactory != this.hibernateTemplate.getSessionFactory()) {18             this.hibernateTemplate = createHibernateTemplate(sessionFactory);19         }20     }21 22     protected HibernateTemplate createHibernateTemplate(SessionFactory sessionFactory) {23         return new HibernateTemplate(sessionFactory);24     }25 26     public final SessionFactory getSessionFactory() {27         return (this.hibernateTemplate != null ? this.hibernateTemplate.getSessionFactory() : null);28     }29 30     public final void setHibernateTemplate(HibernateTemplate hibernateTemplate) {31         this.hibernateTemplate = hibernateTemplate;32     }33 34     public final HibernateTemplate getHibernateTemplate() {35       return this.hibernateTemplate;36     }37 38     @Override39     protected final void checkDaoConfig() {40         if (this.hibernateTemplate == null) {41             throw new IllegalArgumentException("'sessionFactory' or 'hibernateTemplate' is required");42         }43     }44 45 46     protected final Session getSession()47         throws DataAccessResourceFailureException, IllegalStateException {48 49         return getSession(this.hibernateTemplate.isAllowCreate());50     }51 52 53     protected final Session getSession(boolean allowCreate)54         throws DataAccessResourceFailureException, IllegalStateException {55 56         return (!allowCreate ?57             SessionFactoryUtils.getSession(getSessionFactory(), false) :58                 SessionFactoryUtils.getSession(59                         getSessionFactory(),60                         this.hibernateTemplate.getEntityInterceptor(),61                         this.hibernateTemplate.getJdbcExceptionTranslator()));62     }63 64     protected final DataAccessException convertHibernateAccessException(HibernateException ex) {65         return this.hibernateTemplate.convertHibernateAccessException(ex);66     }67 68     protected final void releaseSession(Session session) {69         SessionFactoryUtils.releaseSession(session, getSessionFactory());70     }71 72 }

  从源代码可以看到,属性所需类型确实为org.hibernate.SessionFactory(上述代码16行处可看出)。

  我是偶然发现这一点的,在后来,我顺着LocalSessionFactoryBean的父类或接口向上追溯:

    LocalSessionFactoryBean extends AbstractSessionFactoryBean implements BeanClassLoaderAware

    AbstractSessionFactoryBean extends HibernateExceptionTranslator

  implements FactoryBean<SessionFactory>, InitializingBean, DisposableBean

  在经过分析后,我把重点放在了FactoryBean<SessionFactory>这个接口上,它实际上是一个泛型接口,原型如下:

  org.springframework.beans.factory.FactoryBean源代码(省略了注释):

1 package org.springframework.beans.factory; 2  3 public interface FactoryBean
{ 4 5 T getObject() throws Exception; 6 7 Class
getObjectType(); 8 9 boolean isSingleton();10 11 }

  看到这里,我一度认为自己掌握了这种方式,于是我开始着手进行实验(以下是我进行实验的项目,只是一个添加了Spring支持的Java Project。注意添加Spring的aop支持):

1 import org.springframework.context.ApplicationContext; 2 import org.springframework.context.support.ClassPathXmlApplicationContext; 3  4 public class Test { 5     // main方法,从Spring容器中拿到对象 6     public static void main(String[] args) { 7         ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); 8         System.out.println(ac.getBean("tt")); 9     }10 }11 // 用作实体类,可以看做org.hibernate.SessionFactory12 class E {13 14 }15 // 用做泛型接口,可以看作org.springframework.beans.factory.FactoryBean16 interface MyFactoryBean
{17 18 }19 // 用做真正构造得到的类,可以看作org.springframework.orm.hibernate3.LocalSessionFactoryBean20 class T implements MyFactoryBean
{21 22 }23 // 用作使用实体作为属性的类,可以看作org.springframework.orm.hibernate3.support.HibernateDaoSupport24 class M{25 private E e;26 public void setE(E e){27 this.e = e;28 }29 }
1 
2
7 8
9 10
11
12
13
14
15
16

  这样就可以吗?事实证明:NO!

  ps:也对,这样都行的话,国足能进世界杯(进过吗?不清楚)。

  

  得到一个异常(大家翻译一下就明了):java.lang.IllegalStateException: Cannot convert value of type [T] to required type [E] for property 'e': no matching editors or conversion strategy found。

  看到这个异常,我忽然想到:难道是因为没有类似org.springframework.beans.factory.FactoryBean中的getObject方法?

  于是,我连夜进行测试,在接口和实现中添加方法,改进后如下

1 interface MyFactoryBean
{ 2 T getObject() throws Exception; 3 4 Class
getObjectType(); 5 6 boolean isSingleton(); 7 } 8 class T implements MyFactoryBean
{ 9 10 @Override11 public E getObject() throws Exception {12 return new E();13 }14 15 @Override16 public Class
getObjectType() {17 return E.class;18 }19 20 @Override21 public boolean isSingleton() {22 return false;23 }24 25 }

  结果证明:纯属坑爹,这不是换汤不换药吗?

  最后,我使用了Spring自带的FactoryBean:

1 import org.springframework.beans.factory.FactoryBean; 2 //…… 3 class T implements FactoryBean
{ 4 5 @Override 6 public E getObject() throws Exception { 7 return new E(); 8 } 9 10 @Override11 public Class
getObjectType() {12 return E.class;13 }14 15 @Override16 public boolean isSingleton() {17 return false;18 }19 20 }21 //……

  这才成功了!

  由此可见,Spring用了某种转换来搞定这个事情,其中设计到多种设计模式,下次再深入研究。

 

 

 欢迎您移步我们的交流群,无聊的时候大家一起打发时间:

 或者通过QQ与我联系:

 (最后编辑时间2012-10-11 17:32:29)

  

转载于:https://www.cnblogs.com/Johness/archive/2012/10/11/2720266.html

你可能感兴趣的文章
malloc 实现二维数组
查看>>
P2661 信息传递
查看>>
[HDU] 1025 Constructing Roads In JGShining's Kingdom - 二分的求最大递增非连续子序列
查看>>
decode函数
查看>>
SCP注意事项
查看>>
英国NHS
查看>>
ScrollView嵌套GridView和ListView行高问题
查看>>
测试秒杀新版本3.5 stieserver cms
查看>>
Lua获取当前时间
查看>>
redis5.0主从配置
查看>>
JavaScript严谨模式(Strict Mode)提升开发效率和质量
查看>>
[洛谷P4092][HEOI2016/TJOI2016]树
查看>>
nginx配置比较杂乱的总结
查看>>
docker 真实---安装基本映像 (一)
查看>>
php中使用array_slice将数组中的元素分类
查看>>
关于C#的partial修饰符
查看>>
哨兵元素的应用总结
查看>>
关于Request.PathInfo
查看>>
fiddler抓手机报文的配置指南
查看>>
Linux/CentOS下修改MAC地址
查看>>