JPA,Spring中 Hibernate對JPA實現 如何初始化和得到數據源分析

經過調試,咱們發現是 spring啓動中,hibernate會裝載和初始化 全局配置, 其實就是個 Map。java

在Map中 他會初始化 org.hibernate.cfg.AvailableSettings#DATASOURCE 的key 做爲 map裏數據源的key。git

數據源初始化代碼 位於 org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl#normalizeDataAccess :spring

private void normalizeDataAccess(
			HashMap<?, ?> integrationSettingsCopy,
			MergedSettings mergedSettings,
			PersistenceUnitDescriptor persistenceUnit) {
		if ( dataSource != null ) {
			applyDataSource(
					dataSource,
					// we don't explicitly know
					null,
					integrationSettingsCopy,
					mergedSettings
			);

			// EARLY EXIT!!
			return;
		}

		if ( integrationSettingsCopy.containsKey( DATASOURCE ) ) {
			final Object dataSourceRef = integrationSettingsCopy.remove( DATASOURCE );
			if ( dataSourceRef != null ) {
				applyDataSource(
						dataSourceRef,
						null,
						integrationSettingsCopy,
						mergedSettings
				);

				// EARLY EXIT!!
				return;
			}
		}

		if ( integrationSettingsCopy.containsKey( JPA_JTA_DATASOURCE ) ) {
			final Object dataSourceRef = integrationSettingsCopy.remove( JPA_JTA_DATASOURCE );
			if ( dataSourceRef != null ) {
				applyDataSource(
						dataSourceRef,
						true,
						integrationSettingsCopy,
						mergedSettings
				);

				// EARLY EXIT!!
				return;
			}
		}

		if ( integrationSettingsCopy.containsKey( JPA_NON_JTA_DATASOURCE ) ) {
			final Object dataSourceRef = integrationSettingsCopy.remove( JPA_NON_JTA_DATASOURCE );

			applyDataSource(
					dataSourceRef,
					false,
					integrationSettingsCopy,
					mergedSettings
			);

			// EARLY EXIT!!
			return;
		}

		if ( integrationSettingsCopy.containsKey( URL ) ) {
			// these have precedence over the JPA ones
			final Object integrationJdbcUrl = integrationSettingsCopy.get( URL );
			if ( integrationJdbcUrl != null ) {
				//noinspection unchecked
				applyJdbcSettings(
						integrationJdbcUrl,
						NullnessHelper.coalesceSuppliedValues(
								() -> ConfigurationHelper.getString( DRIVER, integrationSettingsCopy ),
								() -> ConfigurationHelper.getString( JPA_JDBC_DRIVER, integrationSettingsCopy ),
								() -> ConfigurationHelper.getString( DRIVER, mergedSettings.configurationValues ),
								() -> ConfigurationHelper.getString( JPA_JDBC_DRIVER, mergedSettings.configurationValues )
						),
						integrationSettingsCopy,
						mergedSettings
				);

				// EARLY EXIT!!
				return;
			}
		}

		if ( integrationSettingsCopy.containsKey( JPA_JDBC_URL ) ) {
			final Object integrationJdbcUrl = integrationSettingsCopy.get( JPA_JDBC_URL );

			if ( integrationJdbcUrl != null ) {
				//noinspection unchecked
				applyJdbcSettings(
						integrationJdbcUrl,
						NullnessHelper.coalesceSuppliedValues(
								() -> ConfigurationHelper.getString( JPA_JDBC_DRIVER, integrationSettingsCopy ),
								() -> ConfigurationHelper.getString( JPA_JDBC_DRIVER, mergedSettings.configurationValues )
						),
						integrationSettingsCopy,
						mergedSettings
				);

				// EARLY EXIT!!
				return;
			}
		}

		if ( persistenceUnit.getJtaDataSource() != null ) {
			applyDataSource(
					persistenceUnit.getJtaDataSource(),
					true,
					integrationSettingsCopy,
					mergedSettings
			);

			// EARLY EXIT!!
			return;
		}

		if ( persistenceUnit.getNonJtaDataSource() != null ) {
			applyDataSource(
					persistenceUnit.getNonJtaDataSource(),
					false,
					integrationSettingsCopy,
					mergedSettings
			);

			// EARLY EXIT!!
			return;
		}

		if ( mergedSettings.configurationValues.containsKey( URL ) ) {
			final Object url = mergedSettings.configurationValues.get( URL );

			if ( url != null && ( ! ( url instanceof String ) || StringHelper.isNotEmpty( (String) url ) ) ) {
				applyJdbcSettings(
						url,
						ConfigurationHelper.getString( DRIVER, mergedSettings.configurationValues ),
						integrationSettingsCopy,
						mergedSettings
				);

				// EARLY EXIT!!
				return;
			}
		}

		if ( mergedSettings.configurationValues.containsKey( JPA_JDBC_URL ) ) {
			final Object url = mergedSettings.configurationValues.get( JPA_JDBC_URL );

			if ( url != null && ( ! ( url instanceof String ) || StringHelper.isNotEmpty( (String) url ) ) ) {
				applyJdbcSettings(
						url,
						ConfigurationHelper.getString( JPA_JDBC_DRIVER, mergedSettings.configurationValues ),
						integrationSettingsCopy,
						mergedSettings
				);

				// EARLY EXIT!!
				return;
			}
		}

		// any other conditions to account for?
	}

經過代碼能夠看出 他會優先幾個 key,看是否已經有了,有就沿用這些key裏的數據源。mybatis

個人項目目前都沒有,代碼往下走,到了 app

if ( persistenceUnit.getNonJtaDataSource() != null ) { 這一行, 發如今 org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor#getNonJtaDataSource 獲取了數據源:

轉而調用了 javax.persistence.spi.PersistenceUnitInfo#getNonJtaDataSource :ui

發現真正的實現類是:org.springframework.orm.jpa.persistenceunit.SpringPersistenceUnitInfo  的 getNonJtaDataSource 方法。url

而後最終調用了 : org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo#getNonJtaDataSource  這個方法返回了 這個類的實例變量spa

org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo#nonJtaDataSource , 因此咱們繼續看 實例變量是如何初始化的:hibernate

最終發現 是  org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration 初始化的, 而他是由 org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration 導入的。調試

 

而後發現 最後DataSource來自於 spring boot autoconfig包的 org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration 類,

HibernateJpaConfiguration  直接繼承的他, 默認的DataSource對象也是 JpaBaseConfiguration  實例字段。

org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration#dataSource 而這個字段則是直接經過 類構造方法 讓spring自動ioc的。

題外話:關於 JPA實現相似mybatis的動態效果,能夠參考下大佬的開源:   https://gitee.com/it00021hot/fenix 

相關文章
相關標籤/搜索