JPA,Spring中 Hibernate对JPA实现 如何初始化和获得数据源分析

原创
09/23 14:22
阅读数 2K

通过调试,我们发现是 spring启动中,hibernate会装载和初始化 全局配置, 其实就是个 Map。

在Map中 他会初始化 org.hibernate.cfg.AvailableSettings#DATASOURCE 的key 作为 map里数据源的key。

数据源初始化代码 位于 org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl#normalizeDataAccess :

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里的数据源。

我的项目目前都没有,代码往下走,到了 

if ( persistenceUnit.getNonJtaDataSource() != null ) { 这一行, 发现在 org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor#getNonJtaDataSource 获取了数据源:

转而调用了 javax.persistence.spi.PersistenceUnitInfo#getNonJtaDataSource :

发现真正的实现类是:org.springframework.orm.jpa.persistenceunit.SpringPersistenceUnitInfo  的 getNonJtaDataSource 方法。

然后最终调用了 : org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo#getNonJtaDataSource  这个方法返回了 这个类的实例变量

org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo#nonJtaDataSource , 所以我们继续看 实例变量是如何初始化的:

最终发现 是  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 

 

展开阅读全文
打赏
1
1 收藏
分享
加载中
更多评论
打赏
0 评论
1 收藏
1
分享
返回顶部
顶部