九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
Spring源代碼解析(八):Spring驅(qū)動(dòng)Hibernate的實(shí)現(xiàn)
O/R工具出現(xiàn)之后,簡(jiǎn)化了許多復(fù)雜的信息持久化的開(kāi)發(fā)。Spring應(yīng)用開(kāi)發(fā)者可以通過(guò)Spring提供的O/R方案更方便的使用各種持久化工具,比如Hibernate;下面我們就Spring+Hibernate中的Spring實(shí)現(xiàn)做一個(gè)簡(jiǎn)單的剖析。
Spring對(duì)Hinberanate的配置是通過(guò)LocalSessionFactoryBean來(lái)完成的,這是一個(gè)工廠Bean的實(shí)現(xiàn),在基類(lèi)AbstractSessionFactoryBean中:
Java代碼
  1. /**  

  2.  * 這是FactoryBean需要實(shí)現(xiàn)的接口方法,直接取得當(dāng)前的sessionFactory的值  

  3.  */  

  4. public Object getObject() {   

  5.     return this.sessionFactory;   

  6. }  


這個(gè)值在afterPropertySet中定義:
Java代碼
  1. public void afterPropertiesSet() throws Exception {   

  2.     //這個(gè)buildSessionFactory是通過(guò)配置信息得到SessionFactory的地方   

  3.     SessionFactory rawSf = buildSessionFactory();   

  4.     //這里使用了Proxy方法插入對(duì)getCurrentSession的攔截,得到和事務(wù)相關(guān)的session   

  5.     this.sessionFactory = wrapSessionFactoryIfNecessary(rawSf);   

  6. }  


我們先看看SessionFactory是怎樣創(chuàng)建的,這個(gè)方法很長(zhǎng),包含了創(chuàng)建Hibernate的SessionFactory的詳盡步驟:
Java代碼
  1. protected SessionFactory buildSessionFactory() throws Exception {   

  2.     SessionFactory sf = null;   

  3.     // Create Configuration instance.   

  4.     Configuration config = newConfiguration();   

  5.     //這里配置數(shù)據(jù)源,事務(wù)管理器,LobHander到Holder中,這個(gè)Holder是一個(gè)ThreadLocal變量,這樣這些資源就和線(xiàn)程綁定了   

  6.     if (this.dataSource != null) {   

  7.         // Make given DataSource available for SessionFactory configuration.   

  8.         configTimeDataSourceHolder.set(this.dataSource);   

  9.     }   

  10.     if (this.jtaTransactionManager != null) {   

  11.         // Make Spring-provided JTA TransactionManager available.   

  12.         configTimeTransactionManagerHolder.set(this.jtaTransactionManager);   

  13.     }   

  14.     if (this.lobHandler != null) {   

  15.         // Make given LobHandler available for SessionFactory configuration.   

  16.         // Do early because because mapping resource might refer to custom types.   

  17.         configTimeLobHandlerHolder.set(this.lobHandler);   

  18.     }   

  19.     //這里是使用Hibernate的各個(gè)屬性的配置,這里使用了Configuration類(lèi)來(lái)抽象這些數(shù)據(jù)   

  20.     try {   

  21.         // Set connection release mode "on_close" as default.   

  22.         // This was the case for Hibernate 3.0; Hibernate 3.1 changed   

  23.         // it to "auto" (i.e. "after_statement" or "after_transaction").   

  24.         // However, for Spring's resource management (in particular for   

  25.         // HibernateTransactionManager), "on_close" is the better default.   

  26.         config.setProperty(Environment.RELEASE_CONNECTIONS, ConnectionReleaseMode.ON_CLOSE.toString());   

  27.         if (!isExposeTransactionAwareSessionFactory()) {   

  28.             // Not exposing a SessionFactory proxy with transaction-aware   

  29.             // getCurrentSession() method -> set Hibernate 3.1 CurrentSessionContext   

  30.             // implementation instead, providing the Spring-managed Session that way.   

  31.             // Can be overridden by a custom value for corresponding Hibernate property.   

  32.             config.setProperty(Environment.CURRENT_SESSION_CONTEXT_CLASS,   

  33.                     "org.springframework.orm.hibernate3.SpringSessionContext");   

  34.         }   

  35.         if (this.entityInterceptor != null) {   

  36.             // Set given entity interceptor at SessionFactory level.   

  37.             config.setInterceptor(this.entityInterceptor);   

  38.         }   

  39.         if (this.namingStrategy != null) {   

  40.             // Pass given naming strategy to Hibernate Configuration.   

  41.             config.setNamingStrategy(this.namingStrategy);   

  42.         }   

  43.         if (this.typeDefinitions != null) {   

  44.             // Register specified Hibernate type definitions.   

  45.             Mappings mappings = config.createMappings();   

  46.             for (int i = 0; i < this.typeDefinitions.length; i++) {   

  47.                 TypeDefinitionBean typeDef = this.typeDefinitions[i];   

  48.                 mappings.addTypeDef(typeDef.getTypeName(), typeDef.getTypeClass(), typeDef.getParameters());   

  49.             }   

  50.         }   

  51.         if (this.filterDefinitions != null) {   

  52.             // Register specified Hibernate FilterDefinitions.   

  53.             for (int i = 0; i < this.filterDefinitions.length; i++) {   

  54.                 config.addFilterDefinition(this.filterDefinitions[i]);   

  55.             }   

  56.         }   

  57.         if (this.configLocations != null) {   

  58.             for (int i = 0; i < this.configLocations.length; i++) {   

  59.                 // Load Hibernate configuration from given location.   

  60.                 config.configure(this.configLocations[i].getURL());   

  61.             }   

  62.         }   

  63.         if (this.hibernateProperties != null) {   

  64.             // Add given Hibernate properties to Configuration.   

  65.             config.addProperties(this.hibernateProperties);   

  66.         }   

  67.         if (this.dataSource != null) {   

  68.             boolean actuallyTransactionAware =   

  69.                     (this.useTransactionAwareDataSource || this.dataSource instanceof TransactionAwareDataSourceProxy);   

  70.             // Set Spring-provided DataSource as Hibernate ConnectionProvider.   

  71.             config.setProperty(Environment.CONNECTION_PROVIDER,   

  72.                     actuallyTransactionAware ?   

  73.                     TransactionAwareDataSourceConnectionProvider.class.getName() :   

  74.                     LocalDataSourceConnectionProvider.class.getName());   

  75.         }   

  76.         if (this.jtaTransactionManager != null) {   

  77.             // Set Spring-provided JTA TransactionManager as Hibernate property.   

  78.             config.setProperty(   

  79.                     Environment.TRANSACTION_MANAGER_STRATEGY, LocalTransactionManagerLookup.class.getName());   

  80.         }   

  81.         if (this.mappingLocations != null) {   

  82.             // Register given Hibernate mapping definitions, contained in resource files.   

  83.             for (int i = 0; i < this.mappingLocations.length; i++) {   

  84.                 config.addInputStream(this.mappingLocations[i].getInputStream());   

  85.             }   

  86.         }   

  87.         if (this.cacheableMappingLocations != null) {   

  88.             // Register given cacheable Hibernate mapping definitions, read from the file system.   

  89.             for (int i = 0; i < this.cacheableMappingLocations.length; i++) {   

  90.                 config.addCacheableFile(this.cacheableMappingLocations[i].getFile());   

  91.             }   

  92.         }   

  93.         if (this.mappingJarLocations != null) {   

  94.             // Register given Hibernate mapping definitions, contained in jar files.   

  95.             for (int i = 0; i < this.mappingJarLocations.length; i++) {   

  96.                 Resource resource = this.mappingJarLocations[i];   

  97.                 config.addJar(resource.getFile());   

  98.             }   

  99.         }   

  100.         if (this.mappingDirectoryLocations != null) {   

  101.             // Register all Hibernate mapping definitions in the given directories.   

  102.             for (int i = 0; i < this.mappingDirectoryLocations.length; i++) {   

  103.                 File file = this.mappingDirectoryLocations[i].getFile();   

  104.                 if (!file.isDirectory()) {   

  105.                     throw new IllegalArgumentException(   

  106.                             "Mapping directory location [" + this.mappingDirectoryLocations[i] +   

  107.                             "] does not denote a directory");   

  108.                 }   

  109.                 config.addDirectory(file);   

  110.             }   

  111.         }   

  112.         if (this.entityCacheStrategies != null) {   

  113.             // Register cache strategies for mapped entities.   

  114.             for (Enumeration classNames = this.entityCacheStrategies.propertyNames(); classNames.hasMoreElements();) {   

  115.                 String className = (String) classNames.nextElement();   

  116.                 String[] strategyAndRegion =   

  117.                         StringUtils.commaDelimitedListToStringArray(this.entityCacheStrategies.getProperty(className));   

  118.                 if (strategyAndRegion.length > 1) {   

  119.                     config.setCacheConcurrencyStrategy(className, strategyAndRegion[0], strategyAndRegion[1]);   

  120.                 }   

  121.                 else if (strategyAndRegion.length > 0) {   

  122.                     config.setCacheConcurrencyStrategy(className, strategyAndRegion[0]);   

  123.                 }   

  124.             }   

  125.         }   

  126.         if (this.collectionCacheStrategies != null) {   

  127.             // Register cache strategies for mapped collections.   

  128.             for (Enumeration collRoles = this.collectionCacheStrategies.propertyNames(); collRoles.hasMoreElements();) {   

  129.                 String collRole = (String) collRoles.nextElement();   

  130.                 String[] strategyAndRegion =   

  131.                         StringUtils.commaDelimitedListToStringArray(this.collectionCacheStrategies.getProperty(collRole));   

  132.                 if (strategyAndRegion.length > 1) {   

  133.                     config.setCollectionCacheConcurrencyStrategy(collRole, strategyAndRegion[0], strategyAndRegion[1]);   

  134.                 }   

  135.                 else if (strategyAndRegion.length > 0) {   

  136.                     config.setCollectionCacheConcurrencyStrategy(collRole, strategyAndRegion[0]);   

  137.                 }   

  138.             }   

  139.         }   

  140.         if (this.eventListeners != null) {   

  141.             // Register specified Hibernate event listeners.   

  142.             for (Iterator it = this.eventListeners.entrySet().iterator(); it.hasNext();) {   

  143.                 Map.Entry entry = (Map.Entry) it.next();   

  144.                 Assert.isTrue(entry.getKey() instanceof String, "Event listener key needs to be of type String");   

  145.                 String listenerType = (String) entry.getKey();   

  146.                 Object listenerObject = entry.getValue();   

  147.                 if (listenerObject instanceof Collection) {   

  148.                     Collection listeners = (Collection) listenerObject;   

  149.                     EventListeners listenerRegistry = config.getEventListeners();   

  150.                     Object[] listenerArray =   

  151.                             (Object[]) Array.newInstance(listenerRegistry.getListenerClassFor(listenerType), listeners.size());   

  152.                     listenerArray = listeners.toArray(listenerArray);   

  153.                     config.setListeners(listenerType, listenerArray);   

  154.                 }   

  155.                 else {   

  156.                     config.setListener(listenerType, listenerObject);   

  157.                 }   

  158.             }   

  159.         }   

  160.         // Perform custom post-processing in subclasses.   

  161.         postProcessConfiguration(config);   

  162.         // 這里是根據(jù)Configuration配置創(chuàng)建SessionFactory的地方   

  163.         logger.info("Building new Hibernate SessionFactory");   

  164.         this.configuration = config;   

  165.         sf = newSessionFactory(config);   

  166.     }   

  167.     //最后把和線(xiàn)程綁定的資源清空   

  168.     finally {   

  169.         if (this.dataSource != null) {   

  170.             // Reset DataSource holder.   

  171.             configTimeDataSourceHolder.set(null);   

  172.         }   

  173.         if (this.jtaTransactionManager != null) {   

  174.             // Reset TransactionManager holder.   

  175.             configTimeTransactionManagerHolder.set(null);   

  176.         }   

  177.         if (this.lobHandler != null) {   

  178.             // Reset LobHandler holder.   

  179.             configTimeLobHandlerHolder.set(null);   

  180.         }   

  181.     }   

  182.     // Execute schema update if requested.   

  183.     if (this.schemaUpdate) {   

  184.         updateDatabaseSchema();   

  185.     }   

  186.     return sf;   

  187. }  


而直接調(diào)用org.hibernate.cfg.Configuration來(lái)得到需要的SessionFactory:
Java代碼
  1. protected SessionFactory newSessionFactory(Configuration config) throws HibernateException {   

  2.     return config.buildSessionFactory();   

  3. }  


所以我們這里看到LocalSessionFactory大致起到的一個(gè)讀取資源配置然后生成SessionFactory的作用;當(dāng)然這里在得到 SessionFactory之后,還需要對(duì)session的事務(wù)管理作一些處理 - 使用了一個(gè)Proxy模式對(duì)getCurrentSession方法進(jìn)行了攔截;
Java代碼
  1. //這里先根據(jù)當(dāng)前的SessionFactory的類(lèi)型得到Proxy,然后插入Spring定義好的getCurrentSession攔截器   

  2.     protected SessionFactory getTransactionAwareSessionFactoryProxy(SessionFactory target) {   

  3.         Class sfInterface = SessionFactory.class;   

  4.         if (target instanceof SessionFactoryImplementor) {   

  5.             sfInterface = SessionFactoryImplementor.class;   

  6.         }   

  7.         return (SessionFactory) Proxy.newProxyInstance(sfInterface.getClassLoader(),   

  8.                 new Class[] {sfInterface}, new TransactionAwareInvocationHandler(target));   

  9.     }  


攔截器的實(shí)現(xiàn)如下:
Java代碼
  1. private static class TransactionAwareInvocationHandler implements InvocationHandler {   

  2.     private final SessionFactory target;   

  3.     public TransactionAwareInvocationHandler(SessionFactory target) {   

  4.         this.target = target;   

  5.     }   

  6.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {   

  7.         // Invocation on SessionFactory/SessionFactoryImplementor interface coming in...   

  8.         // 這里對(duì)getCurrentSession方法進(jìn)行攔截,得到一個(gè)和當(dāng)前事務(wù)綁定的session交給用戶(hù)   

  9.         if (method.getName().equals("getCurrentSession")) {   

  10.             // Handle getCurrentSession method: return transactional Session, if any.   

  11.             try {   

  12.                 return SessionFactoryUtils.doGetSession((SessionFactory) proxy, false);   

  13.             }   

  14.             catch (IllegalStateException ex) {   

  15.                 throw new HibernateException(ex.getMessage());   

  16.             }   

  17.         }   

  18.         else if (method.getName().equals("equals")) {   

  19.             // Only consider equal when proxies are identical.   

  20.             return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE);   

  21.         }   

  22.         else if (method.getName().equals("hashCode")) {   

  23.             // Use hashCode of SessionFactory proxy.   

  24.             return new Integer(hashCode());   

  25.         }   

  26.         // 這里是需要運(yùn)行的SessionFactory的目標(biāo)方法   

  27.         try {   

  28.             return method.invoke(this.target, args);   

  29.         }   

  30.         catch (InvocationTargetException ex) {   

  31.             throw ex.getTargetException();   

  32.         }   

  33.     }   

  34. }  


我們看看getCurrentSession的實(shí)現(xiàn),在SessionFactoryUtils中:
Java代碼
  1. private static Session doGetSession(   

  2.             SessionFactory sessionFactory, Interceptor entityInterceptor,   

  3.             SQLExceptionTranslator jdbcExceptionTranslator, boolean allowCreate)   

  4.             throws HibernateException, IllegalStateException {   

  5.         Assert.notNull(sessionFactory, "No SessionFactory specified");   

  6.         //這個(gè)TransactionSynchronizationManager的Resource是一個(gè)ThreadLocal變量,sessionFactory是一個(gè)單例,但ThreadLocal是和線(xiàn)程綁定的   

  7.         //這樣就實(shí)現(xiàn)了Hiberante中常用的通過(guò)ThreadLocal的session管理機(jī)制   

  8.         SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);   

  9.         if (sessionHolder != null && !sessionHolder.isEmpty()) {   

  10.             // pre-bound Hibernate Session   

  11.             Session session = null;   

  12.             if (TransactionSynchronizationManager.isSynchronizationActive() &&   

  13.                     sessionHolder.doesNotHoldNonDefaultSession()) {   

  14.                 // Spring transaction management is active ->   

  15.                 // register pre-bound Session with it for transactional flushing.   

  16.                 session = sessionHolder.getValidatedSession();   

  17.                 if (session != null && !sessionHolder.isSynchronizedWithTransaction()) {   

  18.                     logger.debug("Registering Spring transaction synchronization for existing Hibernate Session");   

  19.                     TransactionSynchronizationManager.registerSynchronization(   

  20.                             new SpringSessionSynchronization(sessionHolder, sessionFactory, jdbcExceptionTranslator, false));   

  21.                     sessionHolder.setSynchronizedWithTransaction(true);   

  22.                     // Switch to FlushMode.AUTO, as we have to assume a thread-bound Session   

  23.                     // with FlushMode.NEVER, which needs to allow flushing within the transaction.   

  24.                     FlushMode flushMode = session.getFlushMode();   

  25.                     if (flushMode.lessThan(FlushMode.COMMIT) &&   

  26.                             !TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {   

  27.                         session.setFlushMode(FlushMode.AUTO);   

  28.                         sessionHolder.setPreviousFlushMode(flushMode);   

  29.                     }   

  30.                 }   

  31.             }   

  32.             else {   

  33.                 // No Spring transaction management active -> try JTA transaction synchronization.   

  34.                 session = getJtaSynchronizedSession(sessionHolder, sessionFactory, jdbcExceptionTranslator);   

  35.             }   

  36.             if (session != null) {   

  37.                 return session;   

  38.             }   

  39.         }   

  40.         //這里直接打開(kāi)一個(gè)Session   

  41.         logger.debug("Opening Hibernate Session");   

  42.         Session session = (entityInterceptor != null ?   

  43.                 sessionFactory.openSession(entityInterceptor) : sessionFactory.openSession());   

  44.         // Use same Session for further Hibernate actions within the transaction.   

  45.         // Thread object will get removed by synchronization at transaction completion.   

  46.         // 把新打開(kāi)的Session放到SessionHolder,然后放到ThreadLocal里面去和線(xiàn)程綁定起來(lái),這個(gè)ThreadLocal是在 TransactionSynchronizationManager中配置好的,可以根據(jù)sessionFactory來(lái)索取   

  47.         // 同時(shí)根據(jù)事務(wù)處理的狀態(tài)來(lái)配置session的屬性,比如把FlushMode設(shè)置為Never,同時(shí)把session和事務(wù)處理關(guān)聯(lián)起來(lái)   

  48.         if (TransactionSynchronizationManager.isSynchronizationActive()) {   

  49.             // We're within a Spring-managed transaction, possibly from JtaTransactionManager.   

  50.             logger.debug("Registering Spring transaction synchronization for new Hibernate Session");   

  51.             SessionHolder holderToUse = sessionHolder;   

  52.             if (holderToUse == null) {   

  53.                 holderToUse = new SessionHolder(session);   

  54.             }   

  55.             else {   

  56.                 holderToUse.addSession(session);   

  57.             }   

  58.             if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {   

  59.                 session.setFlushMode(FlushMode.NEVER);   

  60.             }   

  61.             TransactionSynchronizationManager.registerSynchronization(   

  62.                     new SpringSessionSynchronization(holderToUse, sessionFactory, jdbcExceptionTranslator, true));   

  63.             holderToUse.setSynchronizedWithTransaction(true);   

  64.             if (holderToUse != sessionHolder) {   

  65.                 TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse);   

  66.             }   

  67.         }   

  68.         else {   

  69.             // No Spring transaction management active -> try JTA transaction synchronization.   

  70.             registerJtaSynchronization(session, sessionFactory, jdbcExceptionTranslator, sessionHolder);   

  71.         }   

  72.         // Check whether we are allowed to return the Session.   

  73.         if (!allowCreate && !isSessionTransactional(session, sessionFactory)) {   

  74.             closeSession(session);   

  75.             throw new IllegalStateException("No Hibernate Session bound to thread, " +   

  76.                 "and configuration does not allow creation of non-transactional one here");   

  77.         }   

  78.         return session;   

  79.     }  


這里就是在Spring中為使用Hiberante的SessionFactory以及Session做的準(zhǔn)備工作,在這個(gè)基礎(chǔ)上,用戶(hù)可以通過(guò)使用 HibernateTemplate來(lái)使用Hibernate的O/R功能,和以前看到的一樣這是一個(gè)execute的回調(diào):
Java代碼
  1. public Object execute(HibernateCallback action, boolean exposeNativeSession) throws DataAccessException {   

  2.     Assert.notNull(action, "Callback object must not be null");   

  3.     //這里得到配置好的Hibernate的Session   

  4.     Session session = getSession();   

  5.     boolean existingTransaction = SessionFactoryUtils.isSessionTransactional(session, getSessionFactory());   

  6.     if (existingTransaction) {   

  7.         logger.debug("Found thread-bound Session for HibernateTemplate");   

  8.     }   

  9.     FlushMode previousFlushMode = null;   

  10.     try {   

  11.         previousFlushMode = applyFlushMode(session, existingTransaction);   

  12.         enableFilters(session);   

  13.         Session sessionToExpose = (exposeNativeSession ? session : createSessionProxy(session));   

  14.         //這里是回調(diào)的入口   

  15.         Object result = action.doInHibernate(sessionToExpose);   

  16.         flushIfNecessary(session, existingTransaction);   

  17.         return result;   

  18.     }   

  19.     catch (HibernateException ex) {   

  20.         throw convertHibernateAccessException(ex);   

  21.     }   

  22.     catch (SQLException ex) {   

  23.         throw convertJdbcAccessException(ex);   

  24.     }   

  25.     catch (RuntimeException ex) {   

  26.         // Callback code threw application exception...   

  27.         throw ex;   

  28.     }   

  29.     finally {   

  30.         //如果這個(gè)調(diào)用的方法在一個(gè)事務(wù)當(dāng)中,   

  31.         if (existingTransaction) {   

  32.             logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");   

  33.             disableFilters(session);   

  34.             if (previousFlushMode != null) {   

  35.                 session.setFlushMode(previousFlushMode);   

  36.             }   

  37.         } //否則把Session關(guān)閉   

  38.         else {   

  39.             // Never use deferred close for an explicitly new Session.   

  40.             if (isAlwaysUseNewSession()) {   

  41.                 SessionFactoryUtils.closeSession(session);   

  42.             }   

  43.             else {   

  44.                 SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory());   

  45.             }   

  46.         }   

  47.     }   

  48. }  


我們看看怎樣得到對(duì)應(yīng)的Session的,仍然使用了SessionFactoryUtils的方法doGetSession:
Java代碼
  1. protected Session getSession() {   

  2.     if (isAlwaysUseNewSession()) {   

  3.         return SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor());   

  4.     }   

  5.     else if (!isAllowCreate()) {   

  6.         return SessionFactoryUtils.getSession(getSessionFactory(), false);   

  7.     }   

  8.     else {   

  9.         return SessionFactoryUtils.getSession(   

  10.                 getSessionFactory(), getEntityInterceptor(), getJdbcExceptionTranslator());   

  11.     }   

  12. }  


這樣我們就可以和其他的Template那樣使用Hibernate的基本功能了,使用的時(shí)候Spring已經(jīng)為我們對(duì)Session的獲取和關(guān)閉,事務(wù)處理的綁定做好了封裝 - 從這個(gè)角度看也大大方便了用戶(hù)的使用。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶(hù)發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
OpenSessionInViewFilter源碼分析
junit測(cè)試之hiberante延遲加載問(wèn)題(Could not obtain transaction-synchronized Session for current threa
將Hibernate與Struts結(jié)合
沒(méi)有SPRING,hibernate 延遲加載
hibernate 要點(diǎn)
SSH框架網(wǎng)上商城項(xiàng)目第1戰(zhàn)之整合Struts2、Hibernate4.3和Spring4.2
更多類(lèi)似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服