Spring框架学习【HibernateTemplate对Hibernate的封装】

1.Spring中,不提供具体的ORM实现,而只是为应用提供对ORM产品的集成环境和使用平台,Spring将Hibernate的会话工厂通过IoC容器管理起来,并且将数据源注入,同时Spring为Hibernate提供了更上层的API封装,方便应用调用,本文通过分析相应源码了解Spring对Hibernate支持的实现。

2.AbstractSessionFactoryBean管理Hibernate会话工厂:

使用过Hibernate的人都知道,Hibernate的SessionFactory(会话工厂)是Hibernate的基础,SessionFactory管理Hibernate的相关配置和映射资源,Spring中通过AbstractSessionFactoryBean抽象类来管理Hibernate的会话工厂,AbstractSessionFactoryBean实现Spring的工厂Bean(FactoryBean)接口,因此AbstractSessionFactoryBean是一个Spring的工厂Bean,即Spring管理Hibernate的IoC容器,AbstractSessionFactoryBean的源码如下:

[java] view plaincopyprint?
  1. public abstract class AbstractSessionFactoryBean  
  2.         implements FactoryBean<SessionFactory>, InitializingBean, DisposableBean, PersistenceExceptionTranslator {  
  3.     protected final Log logger = LogFactory.getLog(getClass());  
  4.     //数据源   
  5.     private DataSource dataSource;  
  6. //Hibernate会话使用Spring事务管理器包装的数据源   
  7.     private boolean useTransactionAwareDataSource = false;  
  8.     //从Hibernate会话工厂中获取的当前会话是否暴露给Spring事务来包装   
  9.     private boolean exposeTransactionAwareSessionFactory = true;  
  10.     //Hibernate SQL相关异常转换器   
  11.     private SQLExceptionTranslator jdbcExceptionTranslator;  
  12.     //Hibernate会话工厂   
  13.     private SessionFactory sessionFactory;  
  14.     //为会话工厂设置数据源,如果设置,则覆盖Hibernate配置文件中的数据源设置   
  15.     public void setDataSource(DataSource dataSource) {  
  16.         this.dataSource = dataSource;  
  17.     }  
  18.     public DataSource getDataSource() {  
  19.         return this.dataSource;  
  20.     }  
  21. //设置Hibernate会话工厂是否使用Spring事务(jdbc事务)包装的数据源,   
  22. //true,则使用Spring的jdbc事务;false,则使用Hibernate事务或者JTA   
  23.     public void setUseTransactionAwareDataSource(boolean useTransactionAwareDataSource) {  
  24.         this.useTransactionAwareDataSource = useTransactionAwareDataSource;  
  25.     }  
  26.     protected boolean isUseTransactionAwareDataSource() {  
  27.         return this.useTransactionAwareDataSource;  
  28.     }  
  29.     //为通过Hibernate会话工厂getCurrentSession()方法获得的当前会话设置   
  30. //是否使用Spring会话包装   
  31.     public void setExposeTransactionAwareSessionFactory(boolean exposeTransactionAwareSessionFactory) {  
  32.         this.exposeTransactionAwareSessionFactory = exposeTransactionAwareSessionFactory;  
  33.     }  
  34.     protected boolean isExposeTransactionAwareSessionFactory() {  
  35.         return this.exposeTransactionAwareSessionFactory;  
  36.     }  
  37.         //为Hibernate会话工厂设置JDBC异常转换器,当Hibernate产生的任何由jdbc异常   
  38. //引起的SQL异常时,使用jdbc异常覆盖Hibernate默认的SQL方言(Dialect)异常   
  39.     public void setJdbcExceptionTranslator(SQLExceptionTranslator jdbcExceptionTranslator) {  
  40.         this.jdbcExceptionTranslator = jdbcExceptionTranslator;  
  41.     }  
  42. //创建Hibernate会话工厂,IoC容器初始化回调方法   
  43.     public void afterPropertiesSet() throws Exception {  
  44. //委托模式,调用AbstractSessionFactoryBean子类//LocalSessionFactoryBean实现的方法   
  45.         SessionFactory rawSf = buildSessionFactory();  
  46.         //如果需要,将给定的会话工厂使用代理包装   
  47.         this.sessionFactory = wrapSessionFactoryIfNecessary(rawSf);  
  48.         //钩子方法,Hibernate会话工厂创建成功后,应用自定义处理   
  49.         afterSessionFactoryCreation();  
  50.     }  
  51.     //如果有需要,将给定的Hibernate会话工厂用代理封装   
  52.     protected SessionFactory wrapSessionFactoryIfNecessary(SessionFactory rawSf) {  
  53.         return rawSf;  
  54.     }  
  55.     //应用从Spring管理Hibernate会话工厂的IoC容器中获取SessionFactory   
  56.     protected final SessionFactory getSessionFactory() {  
  57.         if (this.sessionFactory == null) {  
  58.             throw new IllegalStateException("SessionFactory not initialized yet");  
  59.         }  
  60.         return this.sessionFactory;  
  61.     }  
  62.     //当Spring管理Hibernate会话工厂的IoC容器关闭时关闭所创建的会话工厂   
  63.     public void destroy() throws HibernateException {  
  64.         logger.info("Closing Hibernate SessionFactory");  
  65.         try {  
  66.             beforeSessionFactoryDestruction();  
  67.         }  
  68.         finally {  
  69.             this.sessionFactory.close();  
  70.         }  
  71.     }  
  72. //获取单态模式的Hibernate会话工厂   
  73.     public SessionFactory getObject() {  
  74.         return this.sessionFactory;  
  75.     }  
  76.     //获取Hibernate会话工厂的对象类型   
  77.     public Class<? extends SessionFactory> getObjectType() {  
  78.         return (this.sessionFactory != null ? this.sessionFactory.getClass() : SessionFactory.class);  
  79.     }  
  80.     public boolean isSingleton() {  
  81.         return true;  
  82.     }  
  83. //转换异常   
  84.     public DataAccessException translateExceptionIfPossible(RuntimeException ex) {  
  85.         //如果异常时Hibernate异常类型   
  86.         if (ex instanceof HibernateException) {  
  87.             //转换Hibernate异常   
  88.             return convertHibernateAccessException((HibernateException) ex);  
  89.         }  
  90.         //如果不是Hibernate异常,则返回null   
  91.         return null;  
  92.     }  
  93. //转换Hibernate异常   
  94.     protected DataAccessException convertHibernateAccessException(HibernateException ex) {  
  95.        //如果Hibernate会话工厂设置了Jdbc异常转换器,且给定的异常是jdbc异常类型,   
  96.        //则使用设置的jdbc异常转换器转换给定的Hibernate异常   
  97.         if (this.jdbcExceptionTranslator != null && ex instanceof JDBCException) {  
  98.             JDBCException jdbcEx = (JDBCException) ex;  
  99.             return this.jdbcExceptionTranslator.translate(  
  100.                     "Hibernate operation: " + jdbcEx.getMessage(), jdbcEx.getSQL(), jdbcEx.getSQLException());  
  101.         }  
  102. //如果Hibernate会话工厂没有设置jdbc异常转换器,或者给定异常不是jdbc异常   
  103. //类型,则使用Hibernate默认的异常转换器转换   
  104.         return SessionFactoryUtils.convertHibernateAccessException(ex);  
  105.     }  
  106. //创建Hibernate会话工厂   
  107.     protected abstract SessionFactory buildSessionFactory() throws Exception;  
  108.     //钩子方法,Hibernate会话工厂成功创建后操作处理   
  109.     protected void afterSessionFactoryCreation() throws Exception {  
  110.     }  
  111.     //钩子方法,Hibernate会话工厂关闭前操作处理   
  112.     protected void beforeSessionFactoryDestruction() {  
  113.     }  
  114. }  

通过分析Spring对Hibernate会话工厂管理的IoC容器AbstractSessionFactoryBean的源码,我们可以了解到,AbstractSessionFactoryBean继承了InitializingBean接口,并实现了其afterPropertiesSet方法,该方法是在Spring IoC容器初始化完成之后由IoC容器回调的方法,分析AbstractSessionFactoryBean的工作流程如下:

(1).Spring管理Hibernate会话工厂的IoC容器AbstractSessionFactoryBean初始化完成,IoC容器回调afterPropertiesSet方法创建单态模式的Hivbernate会话工厂。

(2).应用通过getObject方法向Spring管理Hibernate会话工厂的IoC容器AbstractSessionFactoryBean索取Hibernate会话工厂。

下面我们继续分析AbstractSessionFactoryBean子类LocalSessionFactoryBean创建Hibernate会话工厂的过程。

3.LocalSessionFactoryBean创建SessionFactory

Spring中管理Hibernate会话工厂的IoC容器AbstractSessionFactoryBean通过委派模式调用其子类LocalSessionFactoryBeanbuildSessionFactory创建Hibernate会话工厂,源码如下:

[java] view plaincopyprint?
  1. //创建Hibernate会话工厂   
  2. protected SessionFactory buildSessionFactory() throws Exception {  
  3.         //获取Hibernate配置   
  4.         Configuration config = newConfiguration();  
  5.         //获取数据源   
  6.         DataSource dataSource = getDataSource();  
  7.         //配置数据源,事务管理器,缓存等等,将这些配置设置当对应的线程局部变量中,   
  8.         //使资源和当前线程绑定起来   
  9.         if (dataSource != null) {  
  10.             //配置数据源   
  11.             configTimeDataSourceHolder.set(dataSource);  
  12.         }  
  13.         if (this.jtaTransactionManager != null) {  
  14.             //配置jta事务管理器    configTimeTransactionManagerHolder.set(this.jtaTransactionManager);   
  15.         }  
  16.         if (this.cacheRegionFactory != null) {  
  17.             //配置缓存区域工厂  configTimeRegionFactoryHolder.set(this.cacheRegionFactory);   
  18.         }  
  19.         if (this.cacheProvider != null) {  
  20.             //配置缓存提供者   
  21.             configTimeCacheProviderHolder.set(this.cacheProvider);  
  22.         }  
  23.         if (this.lobHandler != null) {  
  24.             //配置lob处理器,用于处理clob/blob等大字段类型映射   
  25.             configTimeLobHandlerHolder.set(this.lobHandler);  
  26.         }  
  27.         //Hibernate不允许显示设置类加载器,因此需要暴露相应的线程上下文类加载器   
  28.         Thread currentThread = Thread.currentThread();  
  29.         ClassLoader threadContextClassLoader = currentThread.getContextClassLoader();  
  30.         boolean overrideClassLoader =  
  31.                 (this.beanClassLoader != null && !this.beanClassLoader.equals(threadContextClassLoader));  
  32.         //用当前类加载器覆盖当前线程上下文类加载器   
  33.         if (overrideClassLoader) {  
  34.             currentThread.setContextClassLoader(this.beanClassLoader);  
  35.         }  
  36.         //配置Hibernate相关属性   
  37.         try {  
  38.             //如果Hibernate会话工厂暴露一个会话包装的代理   
  39.             if (isExposeTransactionAwareSessionFactory()) {  
  40.                 //使用Spring管理的Session作为Hibernate当前会话   
  41.                 config.setProperty(  
  42.                         Environment.CURRENT_SESSION_CONTEXT_CLASS, SpringSessionContext.class.getName());  
  43.             }  
  44.         //如果Hibernate会话工厂指定了事务管理器,则使用Hibernate的事务管理器   
  45.             if (this.jtaTransactionManager != null) {  
  46.                 config.setProperty(  
  47.                         Environment.TRANSACTION_STRATEGY, JTATransactionFactory.class.getName());  
  48.                 config.setProperty(  
  49.                         Environment.TRANSACTION_MANAGER_STRATEGY, LocalTransactionManagerLookup.class.getName());  
  50.             }  
  51.             //如果Hibernate会话工厂没有指定事务管理器,则使用Spring管理的事务   
  52.             else {  
  53.                 config.setProperty(  
  54.                         Environment.TRANSACTION_STRATEGY, SpringTransactionFactory.class.getName());  
  55.             }  
  56.             //设置SessionFactory级别的实体拦截器   
  57.             if (this.entityInterceptor != null) {  
  58.                 config.setInterceptor(this.entityInterceptor);  
  59.             }  
  60.             //设置命名规则   
  61.             if (this.namingStrategy != null) {  
  62.                 config.setNamingStrategy(this.namingStrategy);  
  63.             }  
  64.             //注册指定的Hibernate类型定义   
  65.             if (this.typeDefinitions != null) {  
  66.             //通过JDK反射机制,获取Hibernate配置文件中的createMappings方法   
  67.                 Method createMappings = Configuration.class.getMethod("createMappings");  
  68. //通过JDK反射,获取createMappings方法返回的org.hibernate.cfg.Mappings对//象的addTypeDef方法,该方法的三个参数类型为:String,String和Properties   
  69.                 Method addTypeDef = createMappings.getReturnType().getMethod(  
  70.                         "addTypeDef", String.class, String.class, Properties.class);  
  71.                 //通过JDK反射机制调用Hibernate配置中的createMappings方法,   
  72.                 //返回org.hibernate.cfg.Mappings对象   
  73.                 Object mappings = ReflectionUtils.invokeMethod(createMappings, config);  
  74.                 //遍历Hibernate中所有注册的类型定义   
  75.                 for (TypeDefinitionBean typeDef : this.typeDefinitions) {  
  76.                     //通过反射机制,调用org.hibernate.cfg.Mappings对象的   
  77.                     //addTypeDef方法,该方法的三个参数分别为:类型名称,类型实   
  78. //现类,类型参数,为Hibernate添加类型定义   
  79.                     ReflectionUtils.invokeMethod(addTypeDef, mappings,  
  80.                             typeDef.getTypeName(), typeDef.getTypeClass(), typeDef.getParameters());  
  81.                 }  
  82.             }  
  83.             //注册Hibernate过滤器   
  84.             if (this.filterDefinitions != null) {  
  85.                 for (FilterDefinition filterDef : this.filterDefinitions) {  
  86.                     config.addFilterDefinition(filterDef);  
  87.                 }  
  88.             }  
  89.             //从给定资源路径加载Hibernate配置   
  90.             if (this.configLocations != null) {  
  91.                 for (Resource resource : this.configLocations) {  
  92.                     config.configure(resource.getURL());  
  93.                 }  
  94.             }  
  95.             //添加Hibernate属性   
  96.             if (this.hibernateProperties != null) {  
  97.                 config.addProperties(this.hibernateProperties);  
  98.             }  
  99.             //配置数据源   
  100.             if (dataSource != null) {  
  101.                 //Spring中默认的Hibernate数据源连接提供类   
  102.                 Class providerClass = LocalDataSourceConnectionProvider.class;  
  103.                 //如果使用了事务包装数据源或者使用事务包装数据源代理,则使用   
  104.             //TransactionAwareDataSourceConnectionProvider作为连接提供类   
  105.                 if (isUseTransactionAwareDataSource() || dataSource instanceof TransactionAwareDataSourceProxy) {  
  106.                     providerClass = TransactionAwareDataSourceConnectionProvider.class;  
  107.                 }  
  108.                 //如果Hibernate配置文件中指定事务管理策略,则使用   
  109.                 //LocalJtaDataSourceConnectionProvider作为数据源连接提供类   
  110.                 else if (config.getProperty(Environment.TRANSACTION_MANAGER_STRATEGY) != null) {  
  111.                     providerClass = LocalJtaDataSourceConnectionProvider.class;  
  112.                 }  
  113.                 //设置Hibernate的数据源连接提供类   
  114.                 config.setProperty(Environment.CONNECTION_PROVIDER, providerClass.getName());  
  115.             }  
  116.         //如果Hibernate配置中指定了缓存区域工厂,则使用Spring提供的Hibernate   
  117.         //缓存区域工厂   
  118.             if (this.cacheRegionFactory != null) {  
  119.                 config.setProperty(Environment.CACHE_REGION_FACTORY,  
  120.         "org.springframework.orm.hibernate3.LocalRegionFactoryProxy");  
  121.             }  
  122.             //如果Hibernate配置中指定了缓存提供类,则使用Spring提供的   
  123.             //LocalCacheProviderProxy作为Hibernate缓存提供者   
  124.             else if (this.cacheProvider != null) {  
  125.                 config.setProperty(Environment.CACHE_PROVIDER, LocalCacheProviderProxy.class.getName());  
  126.             }  
  127.             //如果Hibernate配置中指定了实体映射资源,则注册给定的Hibernate映射   
  128.             if (this.mappingResources != null) {  
  129.                 //遍历给定的Hibernate映射资源   
  130.                 for (String mapping : this.mappingResources) {  
  131.                     //定位classpath中的Hibernate映射资源   
  132.                     Resource resource = new ClassPathResource(mapping.trim(), this.beanClassLoader);  
  133.                     //将Hibernate映射资源输入流添加到Hibernate配置输入流中   
  134.                     config.addInputStream(resource.getInputStream());  
  135.                 }  
  136.             }  
  137.             //如果Hibernate配置中指定了实体映射文件路径   
  138.             if (this.mappingLocations != null) {  
  139.                 //遍历给定的路径,将Hibernate实体映射文件输入流添加到Hibernate   
  140.                 //配置输入流中   
  141.                 for (Resource resource : this.mappingLocations) {  
  142.                     config.addInputStream(resource.getInputStream());  
  143.                 }  
  144.             }  
  145.             //如果Hibernate配置中指定了缓存映射路径   
  146.             if (this.cacheableMappingLocations != null) {  
  147.                 //将给定的缓存映射文件添加到Hibernate配置的缓存文件中   
  148.                 for (Resource resource : this.cacheableMappingLocations) {  
  149.                     config.addCacheableFile(resource.getFile());  
  150.                 }  
  151.             }  
  152.             //如果Hibernate配置中指定了包含在jar文件中的映射文件路径   
  153.             if (this.mappingJarLocations != null) {  
  154.                 //将包含在jar文件中的映射文件添加到Hibernate配置中   
  155.                 for (Resource resource : this.mappingJarLocations) {  
  156.                     config.addJar(resource.getFile());  
  157.                 }  
  158.             }  
  159.             //如果Hibernate配置中指定了包含映射文件的目录路径   
  160.             if (this.mappingDirectoryLocations != null) {  
  161.                 //将包含映射文件的给定目录添加到Hibernate配置中   
  162.                 for (Resource resource : this.mappingDirectoryLocations) {  
  163.                     File file = resource.getFile();  
  164.                     if (!file.isDirectory()) {  
  165.                         throw new IllegalArgumentException(  
  166.                                 "Mapping directory location [" + resource + "] does not denote a directory");  
  167.                     }  
  168.                     config.addDirectory(file);  
  169.                 }  
  170.             }  
  171.             //编译Hibernate需要的映射信息   
  172.             postProcessMappings(config);  
  173.             config.buildMappings();  
  174.             //如果Hibernate配置中指定了实体缓存策略   
  175.             if (this.entityCacheStrategies != null) {  
  176.                 //为映射实体设置缓存策略   
  177.                 for (Enumeration classNames = this.entityCacheStrategies.propertyNames(); classNames.hasMoreElements();) {  
  178.                     String className = (String) classNames.nextElement();  
  179.                     //获取缓存策略属性值,将csv格式数据转换为字符串数组   
  180.                     String[] strategyAndRegion =            StringUtils.commaDelimitedListToStringArray(this.entityCacheStrategies.getProperty(className));  
  181.                     //如果缓存策略属性值多于2个,则只给Hibernate设置前两个值   
  182.                     if (strategyAndRegion.length > 1) {  
  183. //获取Hibernate配置中的setCacheConcurrencyStrategy方法   
  184.                         Method setCacheConcurrencyStrategy = Configuration.class.getMethod(  
  185.                                 "setCacheConcurrencyStrategy", String.class, String.class, String.class);  
  186.     //通过反射机制调用Hibernate配置对象的setCacheConcurrencyStrategy方法   ReflectionUtils.invokeMethod(setCacheConcurrencyStrategy, config,   
  187.                                 className, strategyAndRegion[0], strategyAndRegion[1]);  
  188.                     }  
  189.                     //缓存策略属性值只有一个,则只需设置一个   
  190.                     else if (strategyAndRegion.length > 0) {  
  191.                         config.setCacheConcurrencyStrategy(className, strategyAndRegion[0]);  
  192.                     }  
  193.                 }  
  194.             }  
  195.             //如果Hibernate配置了集合缓存策略   
  196.             if (this.collectionCacheStrategies != null) {  
  197.                 //为映射的集合注册缓存策略   
  198.                 for (Enumeration collRoles = this.collectionCacheStrategies.propertyNames(); collRoles.hasMoreElements();) {  
  199.                     String collRole = (String) collRoles.nextElement();  
  200.                     String[] strategyAndRegion =                StringUtils.commaDelimitedListToStringArray(this.collectionCacheStrategies.getProperty(collRole));  
  201.                     if (strategyAndRegion.length > 1) {  
  202.             config.setCollectionCacheConcurrencyStrategy(collRole, strategyAndRegion[0], strategyAndRegion[1]);  
  203.                     }  
  204.                     else if (strategyAndRegion.length > 0) {  
  205.                 config.setCollectionCacheConcurrencyStrategy(collRole, strategyAndRegion[0]);  
  206.                     }  
  207.                 }  
  208.             }  
  209.             //注册Hibernate事件监听器   
  210.             if (this.eventListeners != null) {  
  211.                 for (Map.Entry<String, Object> entry : this.eventListeners.entrySet()) {  
  212.                     //监听事件类型   
  213.                     String listenerType = entry.getKey();  
  214.                     //监听类对象   
  215.                     Object listenerObject = entry.getValue();  
  216.                     //如果监听类对象类型是集合   
  217.                     if (listenerObject instanceof Collection) {  
  218.                         Collection<Object> listeners = (Collection<Object>) listenerObject;  
  219.                         EventListeners listenerRegistry = config.getEventListeners();  
  220.                         //获取给定监听类型的所有监听类   
  221.                         Object[] listenerArray =  
  222.                                 (Object[]) Array.newInstance(listenerRegistry.getListenerClassFor(listenerType), listeners.size());  
  223.                         listenerArray = listeners.toArray(listenerArray);  
  224.                         //Hibernate配置设置集合类型的监听类   
  225.                         config.setListeners(listenerType, listenerArray);  
  226.                     }  
  227.                     // Hibernate配置设置普通的监听类   
  228.                     else {  
  229.                         config.setListener(listenerType, listenerObject);  
  230.                     }  
  231.                 }  
  232.             }  
  233.             //Hibernate配置完成,客户自定义处理   
  234.             postProcessConfiguration(config);  
  235.             logger.info("Building new Hibernate SessionFactory");  
  236.             this.configuration = config;  
  237.             //根据Hibernate配置创建SessionFactory对象   
  238.             return newSessionFactory(config);  
  239.         }  
  240.         //清空线程绑定的资源   
  241.         finally {  
  242.             if (dataSource != null) {  
  243.                 configTimeDataSourceHolder.remove();  
  244.             }  
  245.             if (this.jtaTransactionManager != null) {  
  246.                 configTimeTransactionManagerHolder.remove();  
  247.             }  
  248.             if (this.cacheRegionFactory != null) {  
  249.                 configTimeCacheProviderHolder.remove();  
  250.             }  
  251.             if (this.cacheProvider != null) {  
  252.                 configTimeCacheProviderHolder.remove();  
  253.             }  
  254.             if (this.lobHandler != null) {  
  255.                 configTimeLobHandlerHolder.remove();  
  256.             }  
  257.             if (overrideClassLoader) {  
  258.                     currentThread.setContextClassLoader(threadContextClassLoader);  
  259.             }  
  260.         }  
  261.     }  
  262. //根据Hibernate配置创建SessionFactory   
  263. protected SessionFactory newSessionFactory(Configuration config) throws HibernateException {  
  264.         return config.buildSessionFactory();  
  265.     }   

上述代码非常的长,但是所做的工作非常的清楚,即获取Hibernate的配置,然后设置Hibernate配置,最后生成SessionFactory的过程。

4.HibernateTemplate实现:

Springjdbc封装类似,Spring使用HibernateTemplateHibernate也进行了一下API封装,通过execute回调来调用Hibernate的相关操作处理,接下来简单分析HibernateTemplate的核心实现。

(1). execute相关方法的实现:

JdbcTemplate类似,execute相关方法也是HibernateTemplate的基础核心方法,在execute相关方法中,Spring提供获取Hibernate Session,为当前的Session进行事务处理等通用的操作,源码如下:

[java] view plaincopyprint?
  1. //最基础的execute方法   
  2. public <T> T execute(HibernateCallback<T> action) throws DataAccessException {  
  3.         return doExecute(action, false, false);  
  4.     }   
  5. //需要在新的Hibernate Session中执行的execute方法   
  6. public <T> T executeWithNewSession(HibernateCallback<T> action) {  
  7.         return doExecute(action, true, false);  
  8.     }   
  9. //需要在Hibernate本地Session中执行的execute方法   
  10. public <T> T executeWithNativeSession(HibernateCallback<T> action) {  
  11.         return doExecute(action, false, true);  
  12.     }   
  13. //真正调用Hibernate API的地方   
  14. protected <T> T doExecute(HibernateCallback<T> action, boolean enforceNewSession, boolean enforceNativeSession)  
  15.             throws DataAccessException {  
  16.         Assert.notNull(action, "Callback object must not be null");  
  17.         //获取Hibernate会话,判断是否需要新的Session   
  18.         Session session = (enforceNewSession ?  
  19.                 SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor()) : getSession());  
  20.         //是否存在事务   
  21.         boolean existingTransaction = (!enforceNewSession &&  
  22.                 (!isAllowCreate() || SessionFactoryUtils.isSessionTransactional(session, getSessionFactory())));  
  23.         if (existingTransaction) {  
  24.             logger.debug("Found thread-bound Session for HibernateTemplate");  
  25.         }  
  26.         //刷新模式   
  27.         FlushMode previousFlushMode = null;  
  28.         try {  
  29.             //根据Hibernate Session和事务类型应用相应的刷新模式   
  30.             previousFlushMode = applyFlushMode(session, existingTransaction);  
  31.             //对Session开启过滤器   
  32.             enableFilters(session);  
  33.             //判断Hibernate Session是否需要代理包装   
  34.             Session sessionToExpose =  
  35.                     (enforceNativeSession || isExposeNativeSession() ? session : createSessionProxy(session));  
  36.             //对HibernateCallBack中回调函数的调用,真正调用Hibernate API   
  37.             T result = action.doInHibernate(sessionToExpose);  
  38.             flushIfNecessary(session, existingTransaction);  
  39.             return result;  
  40.         }  
  41.         catch (HibernateException ex) {  
  42.             throw convertHibernateAccessException(ex);  
  43.         }  
  44.         catch (SQLException ex) {  
  45.             throw convertJdbcAccessException(ex);  
  46.         }  
  47.         catch (RuntimeException ex) {  
  48.             throw ex;  
  49.         }  
  50.         finally {  
  51.             //如果存在事务,则调用完毕之后不关闭Session   
  52.             if (existingTransaction) {  
  53.                 logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");  
  54.                 //对Session禁用过滤器   
  55.                 disableFilters(session);  
  56.                 if (previousFlushMode != null) {  
  57.                     session.setFlushMode(previousFlushMode);  
  58.                 }  
  59.             }  
  60.             //如果不存在事务,则关闭当前的Session   
  61.             else {  
  62.                 if (isAlwaysUseNewSession()) {  
  63.                     SessionFactoryUtils.closeSession(session);  
  64.                 }  
  65.                 else {  
  66.     SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory());  
  67.                 }  
  68.             }  
  69.         }  
  70.     }  

(2).HibernateTemplate中增删改查操作的简单实现:

以查询为例,分析HibernateTemplate如何通过execute方法回调Hibernate相应的API,源码如下:

[java] view plaincopyprint?
  1. //查询指定Id的实体   
  2. public Object get(String entityName, Serializable id) throws DataAccessException {  
  3.         return get(entityName, id, null);  
  4.     }  
  5. //真正调用Hibernate API查询的方法   
  6. public Object get(final String entityName, final Serializable id, final LockMode lockMode)  
  7.             throws DataAccessException {  
  8.         //调用Hibernate本地查询方法,参数是一个实现HibernateCallback接口的   
  9.         //匿名内部类,用于execute方法回调   
  10.         return executeWithNativeSession(new HibernateCallback<Object>() {  
  11.             //execute方法回调,真正调用Hibernate查询的方法   
  12.             public Object doInHibernate(Session session) throws HibernateException {  
  13.                 if (lockMode != null) {  
  14.                     return session.get(entityName, id, lockMode);  
  15.                 }  
  16.                 else {  
  17.                     return session.get(entityName, id);  
  18.                 }  
  19.             }  
  20.         });  
  21.     }  

其他的loadupdate等等调用Hibernate的方法类似,各自提供不同的HibernateCallback回调来真正调用Hibernate相应方法。

5.Hibernate管理Session:

在4分析HibernateTemplate的doExecute法源码时我们看到,Spring根据是否需要新Session的判断,使用getSessiongetNewSession两种不同的获取Session的方法,Spring中通过SessionFactoryUtils来管理HibernateSession,分析SessionFactoryUtils管理Session的实现源码:

(1).getNewSession实现:

[java] view plaincopyprint?
  1. //获取新Session   
  2. public static Session getNewSession(SessionFactory sessionFactory, Interceptor entityInterceptor) {  
  3.         Assert.notNull(sessionFactory, "No SessionFactory specified");  
  4.         try {  
  5.             //获取事务管理器中的sessionFactory线程局部变量   
  6.             SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);  
  7.             //如果当前线程绑定了SessionFactory资源   
  8.             if (sessionHolder != null && !sessionHolder.isEmpty()) {  
  9.                 //如果有实体拦截器,则打开一个有实体拦截器的Session连接   
  10.                 if (entityInterceptor != null) {  
  11.                     return sessionFactory.openSession(sessionHolder.getAnySession().connection(), entityInterceptor);  
  12.                 }  
  13.                 //如果没有实体拦截器,则直接打开当前线程中绑定的Session连接   
  14.                 else {  
  15.                     return sessionFactory.openSession(sessionHolder.getAnySession().connection());  
  16.                 }  
  17.             }  
  18.             //如果当前线程没有绑定SessionFactory资源   
  19.             else {  
  20.                 //如果有实体拦截器   
  21.                 if (entityInterceptor != null) {  
  22.                     //打开一个包含给定实体拦截器的Session   
  23.                     return sessionFactory.openSession(entityInterceptor);  
  24.                 }  
  25.                 //如果没有实体拦截器,则直接打开一个新的Session   
  26.                 else {  
  27.                     return sessionFactory.openSession();  
  28.                 }  
  29.             }  
  30.         }  
  31.         catch (HibernateException ex) {  
  32.             throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex);  
  33.         }  
  34.     }  

(2).getSession实现:

[java] view plaincopyprint?
  1. //获取Hibernate Session的入口方法   
  2. public static Session getSession(SessionFactory sessionFactory, boolean allowCreate)  
  3.             throws DataAccessResourceFailureException, IllegalStateException {  
  4.         try {  
  5.             //通过调用doGetSession来获取Hibernate Session   
  6.             return doGetSession(sessionFactory, null, null, allowCreate);  
  7.         }  
  8.         catch (HibernateException ex) {  
  9.             throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex);  
  10.         }  
  11.     }   
  12. //获取Hibernate Session   
  13. private static Session doGetSession(  
  14.             SessionFactory sessionFactory, Interceptor entityInterceptor,  
  15.             SQLExceptionTranslator jdbcExceptionTranslator, boolean allowCreate)  
  16.             throws HibernateException, IllegalStateException {  
  17.         Assert.notNull(sessionFactory, "No SessionFactory specified");  
  18.         //获取和当前线程绑定的Session资源   
  19.         SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);  
  20.         //如果当前线程有绑定了Session的资源,即已经有创建了的Session   
  21.         if (sessionHolder != null && !sessionHolder.isEmpty()) {  
  22.             Session session = null;  
  23.             //如果Spring事务管理是activate的   
  24.             if (TransactionSynchronizationManager.isSynchronizationActive() &&  
  25.                     sessionHolder.doesNotHoldNonDefaultSession()) {  
  26.                 //获取当前线程绑定的有效Session   
  27.                 session = sessionHolder.getValidatedSession();  
  28.                 //如果获取了当前线程绑定的有效Session,并且当前线程绑定的Session   
  29.                 //资源是事务同步的   
  30.                 if (session != null && !sessionHolder.isSynchronizedWithTransaction()) {  
  31.                     logger.debug("Registering Spring transaction synchronization for existing Hibernate Session");  
  32. //为已有的Hibernate Session注册Spring事务同步   
  33.     TransactionSynchronizationManager.registerSynchronization(  
  34.                             new SpringSessionSynchronization(sessionHolder, sessionFactory, jdbcExceptionTranslator, false));  
  35.                     sessionHolder.setSynchronizedWithTransaction(true);  
  36.                     //根据实现级别设置Session刷新模式   
  37.                     FlushMode flushMode = session.getFlushMode();  
  38.                     if (flushMode.lessThan(FlushMode.COMMIT) &&  
  39.                             !TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {  
  40.                         session.setFlushMode(FlushMode.AUTO);  
  41.                         sessionHolder.setPreviousFlushMode(flushMode);  
  42.                     }  
  43.                 }  
  44.             }  
  45.             //如果没有Spring管理的事务   
  46.             else {  
  47.                 //使用jta事务同步   
  48.                 session = getJtaSynchronizedSession(sessionHolder, sessionFactory, jdbcExceptionTranslator);  
  49.             }  
  50.             if (session != null) {  
  51.                 return session;  
  52.             }  
  53.         }  
  54.         logger.debug("Opening Hibernate Session");  
  55.         //当前线程没有绑定Session资源,则需要创建新Session   
  56.         Session session = (entityInterceptor != null ?  
  57.                 sessionFactory.openSession(entityInterceptor) : sessionFactory.openSession());  
  58.         //如果Spring管理的事务是activate的   
  59.         if (TransactionSynchronizationManager.isSynchronizationActive()) {  
  60.             logger.debug("Registering Spring transaction synchronization for new Hibernate Session");  
  61.             SessionHolder holderToUse = sessionHolder;  
  62.             //将新创建的Session添加到当前线程局部变量中   
  63.             if (holderToUse == null) {  
  64.                 holderToUse = new SessionHolder(session);  
  65.             }  
  66.             else {  
  67.                 holderToUse.addSession(session);  
  68.             }  
  69.             //设置Session刷新模式   
  70.             if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {  
  71.                 session.setFlushMode(FlushMode.MANUAL);  
  72.             }  
  73.             //为新创建的Hibernate Session注册Spring事务   
  74.             TransactionSynchronizationManager.registerSynchronization(  
  75.                     new SpringSessionSynchronization(holderToUse, sessionFactory, jdbcExceptionTranslator, true));  
  76.             holderToUse.setSynchronizedWithTransaction(true);  
  77.             //将新创建的Session与当前线资源程绑定   
  78.             if (holderToUse != sessionHolder) {  
  79.         TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse);  
  80.             }  
  81.         }  
  82.         //如果没有Spring事务   
  83.         else {  
  84.             //为Session设置JTA事务   
  85.             registerJtaSynchronization(session, sessionFactory, jdbcExceptionTranslator, sessionHolder);  
  86.         }  
  87.         //判断是否允许返回给定的Session   
  88.         if (!allowCreate && !isSessionTransactional(session, sessionFactory)) {  
  89.             closeSession(session);  
  90.             throw new IllegalStateException("No Hibernate Session bound to thread, " +  
  91.                 "and configuration does not allow creation of non-transactional one here");  
  92.         }  
  93.         return session;  
  94.     }  

通过上面SpringHibernate Session管理的源码分析,我们了解到Spring已经将Hibernate Session的获取与关闭,Session的事务处理,以及Session与线程资源绑定等操作做了封装统一管理,为应用使用Hibernate提供了方便。

Spring框架学习【HibernateTemplate对Hibernate的封装】

上一篇:MyReport报表引擎2.7.0.0新功能


下一篇:Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)