springboot 加载jpa,datasource的初始化流程

一、在application.yml在配置datasource的参数,hibernate,jpa的参数。

spring:
  datasource:
    url: jdbc:mysql://**
    username: ***
    password: ***
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    initialSize: 1
    minIdle: 3
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 30000
    validationQuery: select 'x'
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    filters: stat,wall,slf4j
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
    useGlobalDataSourceStat: true
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: none

在启动类上或者配置类上加上@EnableJpaRepositories注解,就会自动初始化配置jpa。

二、首先我们看搜索dao接口对象定义的流程

1.当spring容器搜索到@EnableJpaRepositories类时,会自动调用此注解所包含的@Import(JpaRepositoriesRegistrar.class)类来把新搜索到的类定义加载到容器工厂中。

@Inherited
@Import(JpaRepositoriesRegistrar.class)
public @interface EnableJpaRepositories {

2.然后会调到org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport.registerBeanDefinitions 注册BEAN 定义对象。

    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry, BeanNameGenerator generator) {
        Assert.notNull(metadata, "AnnotationMetadata must not be null!");
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null!");
        Assert.notNull(this.resourceLoader, "ResourceLoader must not be null!");
        if (metadata.getAnnotationAttributes(this.getAnnotation().getName()) != null) {
            AnnotationRepositoryConfigurationSource configurationSource = new AnnotationRepositoryConfigurationSource(metadata, this.getAnnotation(), this.resourceLoader, this.environment, registry, generator);
            RepositoryConfigurationExtension extension = this.getExtension();
            RepositoryConfigurationUtils.exposeRegistration(extension, registry, configurationSource);
            RepositoryConfigurationDelegate delegate = new RepositoryConfigurationDelegate(configurationSource, this.resourceLoader, this.environment);
            delegate.registerRepositoriesIn(registry, extension);
        }
    }

3.在扫描DAO包时org.springframework.data.repository.config.

RepositoryConfigurationSourceSupport.getCandidates,
   public Streamable<BeanDefinition> getCandidates(ResourceLoader loader) {
        RepositoryComponentProvider scanner = new RepositoryComponentProvider(this.getIncludeFilters(), this.registry);
        scanner.setConsiderNestedRepositoryInterfaces(this.shouldConsiderNestedRepositories());
        scanner.setEnvironment(this.environment);
        scanner.setResourceLoader(loader);
        this.getExcludeFilters().forEach((it) -> {
            scanner.addExcludeFilter(it);
        });
        return Streamable.of(() -> {
            return this.getBasePackages().stream().flatMap((it) -> {
                return scanner.findCandidateComponents(it).stream();
            });
        });
    }

4.在创建RepositoryComponentProvider的构造方法中,会加入Repository注解,RepositoryDefinition类的include filter,

public RepositoryComponentProvider(Iterable<? extends TypeFilter> includeFilters, BeanDefinitionRegistry registry) {

		super(false);

		Assert.notNull(includeFilters, "Include filters must not be null!");
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null!");

		this.registry = registry;

		if (includeFilters.iterator().hasNext()) {
			for (TypeFilter filter : includeFilters) {
				addIncludeFilter(filter);
			}
		} else {
			super.addIncludeFilter(new InterfaceTypeFilter(Repository.class));
			super.addIncludeFilter(new AnnotationTypeFilter(RepositoryDefinition.class, true, true));
		}

		addExcludeFilter(new AnnotationTypeFilter(NoRepositoryBean.class));
	}

5.RepositoryComponentProvider继承于ClassPathScanningCandidateComponentProvider 这里面实际上是调用

ClassPathScanningCandidateComponentProvider.scanCandidateComponents去搜索指定包目录下的符合条件的对象。
  public Set<BeanDefinition> findCandidateComponents(String basePackage) {
        Set<BeanDefinition> candidates = super.findCandidateComponents(basePackage);
        Iterator var3 = candidates.iterator();

        while(var3.hasNext()) {
            BeanDefinition candidate = (BeanDefinition)var3.next();
            if (candidate instanceof AnnotatedBeanDefinition) {
                AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition)candidate);
            }
        }

        return candidates;
    }

 这里面搜索到的candidates为所有系统中的dao文件。

三、dataSource对象的加载过程

1.org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,这个类在有配置spring.datasource.type时使用PooledDataSourceConfiguration初始化配置(即是外部指定数据源池),没有时使用EmbeddedDatabaseConfiguration初始化配置。
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.class })
public class DataSourceAutoConfiguration {

	@Configuration(proxyBeanMethods = false)
	@Conditional(EmbeddedDatabaseCondition.class)
	@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
	@Import(EmbeddedDataSourceConfiguration.class)
	protected static class EmbeddedDatabaseConfiguration {

	}

	@Configuration(proxyBeanMethods = false)
	@Conditional(PooledDataSourceCondition.class)
	@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
	@Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
			DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.Generic.class,
			DataSourceJmxConfiguration.class })
	protected static class PooledDataSourceConfiguration {

	}

	/**
	 * {@link AnyNestedCondition} that checks that either {@code spring.datasource.type}
	 * is set or {@link PooledDataSourceAvailableCondition} applies.
	 */
	static class PooledDataSourceCondition extends AnyNestedCondition {

		PooledDataSourceCondition() {
			super(ConfigurationPhase.PARSE_CONFIGURATION);
		}

		@ConditionalOnProperty(prefix = "spring.datasource", name = "type")
		static class ExplicitType {

		}


	}


	/**
	 * {@link Condition} to detect when an embedded {@link DataSource} type can be used.
	 * If a pooled {@link DataSource} is available, it will always be preferred to an
	 * {@code EmbeddedDatabase}.
	 */
	static class EmbeddedDatabaseCondition extends SpringBootCondition {

		private static final String DATASOURCE_URL_PROPERTY = "spring.datasource.url";

		private final SpringBootCondition pooledCondition = new PooledDataSourceCondition();


	}

}

2.由于我们指定的spring.datasource.type=com.alibaba.druid.pool.DruidDataSource,所以加载外部数据源连接池配置。然后会加载到DataSourceConfiguration.Generic会根据TYPE去创建数据源。

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnMissingBean(DataSource.class)
	@ConditionalOnProperty(name = "spring.datasource.type")
	static class Generic {

		@Bean
		DataSource dataSource(DataSourceProperties properties) {
			return properties.initializeDataSourceBuilder().build();
		}

	}

3.org.springframework.boot.jdbc.DataSourceBuilder去创建数据源。

	public T build() {
		Class<? extends DataSource> type = getType();
		DataSource result = BeanUtils.instantiateClass(type);
		maybeGetDriverClassName();
		bind(result);
		return (T) result;
	}

四、org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration进行jpa的几个对象初始化。

1.org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration会import导入HibernateJpaConfiguration.class,
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(HibernateProperties.class)
@ConditionalOnSingleCandidate(DataSource.class)
class HibernateJpaConfiguration extends JpaBaseConfiguration {

	HibernateJpaConfiguration(DataSource dataSource, JpaProperties jpaProperties,
			ConfigurableListableBeanFactory beanFactory, ObjectProvider<JtaTransactionManager> jtaTransactionManager,
			HibernateProperties hibernateProperties,
			ObjectProvider<Collection<DataSourcePoolMetadataProvider>> metadataProviders,
			ObjectProvider<SchemaManagementProvider> providers,
			ObjectProvider<PhysicalNamingStrategy> physicalNamingStrategy,
			ObjectProvider<ImplicitNamingStrategy> implicitNamingStrategy,
			ObjectProvider<HibernatePropertiesCustomizer> hibernatePropertiesCustomizers) {
		super(dataSource, jpaProperties, jtaTransactionManager);
		this.hibernateProperties = hibernateProperties;
		this.defaultDdlAutoProvider = new HibernateDefaultDdlAutoProvider(providers);
		this.poolMetadataProvider = new CompositeDataSourcePoolMetadataProvider(metadataProviders.getIfAvailable());
		this.hibernatePropertiesCustomizers = determineHibernatePropertiesCustomizers(
				physicalNamingStrategy.getIfAvailable(), implicitNamingStrategy.getIfAvailable(), beanFactory,
				hibernatePropertiesCustomizers.orderedStream().collect(Collectors.toList()));
	}

	@Override
	protected AbstractJpaVendorAdapter createJpaVendorAdapter() {
		return new HibernateJpaVendorAdapter();
	}

	@Override
	protected Map<String, Object> getVendorProperties() {
		Supplier<String> defaultDdlMode = () -> this.defaultDdlAutoProvider.getDefaultDdlAuto(getDataSource());
		return new LinkedHashMap<>(this.hibernateProperties
				.determineHibernateProperties(getProperties().getProperties(), new HibernateSettings()
						.ddlAuto(defaultDdlMode).hibernatePropertiesCustomizers(this.hibernatePropertiesCustomizers)));
	}


	
	

}
2.而HibernateJpaConfiguration这个类又继承于org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration,所以会加载JpaBaseConfiguration的@BEAN配置。这里面会创建几个JPA的重要对象,如
EntityManagerFactoryBuilder用来创建实体管理器的工厂对象。
JpaVendorAdapter为jpa厂商适配器。主要用来指定实现JPA的具体组件,如HIBERNATE等。
LocalContainerEntityManagerFactoryBean用来创建具体的实体管理器工厂对象。
PlatformTransactionManager用来创建事务管理器。

@Import(DataSourceInitializedPublisher.Registrar.class)
public abstract class JpaBaseConfiguration implements BeanFactoryAware {

	private final DataSource dataSource;

	private final JpaProperties properties;

	private final JtaTransactionManager jtaTransactionManager;

	private ConfigurableListableBeanFactory beanFactory;

	protected JpaBaseConfiguration(DataSource dataSource, JpaProperties properties,
			ObjectProvider<JtaTransactionManager> jtaTransactionManager) {
		this.dataSource = dataSource;
		this.properties = properties;
		this.jtaTransactionManager = jtaTransactionManager.getIfAvailable();
	}

	@Bean
	@ConditionalOnMissingBean
	public PlatformTransactionManager transactionManager(
			ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
		JpaTransactionManager transactionManager = new JpaTransactionManager();
		transactionManagerCustomizers.ifAvailable((customizers) -> customizers.customize(transactionManager));
		return transactionManager;
	}

	@Bean
	@ConditionalOnMissingBean
	public JpaVendorAdapter jpaVendorAdapter() {
		AbstractJpaVendorAdapter adapter = createJpaVendorAdapter();
		adapter.setShowSql(this.properties.isShowSql());
		if (this.properties.getDatabase() != null) {
			adapter.setDatabase(this.properties.getDatabase());
		}
		if (this.properties.getDatabasePlatform() != null) {
			adapter.setDatabasePlatform(this.properties.getDatabasePlatform());
		}
		adapter.setGenerateDdl(this.properties.isGenerateDdl());
		return adapter;
	}

	@Bean
	@ConditionalOnMissingBean
	public EntityManagerFactoryBuilder entityManagerFactoryBuilder(JpaVendorAdapter jpaVendorAdapter,
			ObjectProvider<PersistenceUnitManager> persistenceUnitManager,
			ObjectProvider<EntityManagerFactoryBuilderCustomizer> customizers) {
		EntityManagerFactoryBuilder builder = new EntityManagerFactoryBuilder(jpaVendorAdapter,
				this.properties.getProperties(), persistenceUnitManager.getIfAvailable());
		customizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
		return builder;
	}

	@Bean
	@Primary
	@ConditionalOnMissingBean({ LocalContainerEntityManagerFactoryBean.class, EntityManagerFactory.class })
	public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder factoryBuilder) {
		Map<String, Object> vendorProperties = getVendorProperties();
		customizeVendorProperties(vendorProperties);
		return factoryBuilder.dataSource(this.dataSource).packages(getPackagesToScan()).properties(vendorProperties)
				.mappingResources(getMappingResources()).jta(isJta()).build();
	}

	protected abstract AbstractJpaVendorAdapter createJpaVendorAdapter();

	protected abstract Map<String, Object> getVendorProperties();

3.创建org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration实例化对象。这个会初始化数据源。

	protected JpaBaseConfiguration(DataSource dataSource, JpaProperties properties,
			ObjectProvider<JtaTransactionManager> jtaTransactionManager) {
		this.dataSource = dataSource;
		this.properties = properties;
		this.jtaTransactionManager = jtaTransactionManager.getIfAvailable();
	}

 4.创建jpaVendorAdapter对象。可以看到JPA厂商适配器对象,目前用的最多是hibernate,系统中有一个实现。

 

 这里指定实体管理器和其工厂类的实现对象。

public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {

	private final HibernateJpaDialect jpaDialect = new HibernateJpaDialect();

	private final PersistenceProvider persistenceProvider;

	private final Class<? extends EntityManagerFactory> entityManagerFactoryInterface;

	private final Class<? extends EntityManager> entityManagerInterface;


	@SuppressWarnings("deprecation")
	public HibernateJpaVendorAdapter() {
		this.persistenceProvider = new SpringHibernateJpaPersistenceProvider();
		this.entityManagerFactoryInterface = org.hibernate.jpa.HibernateEntityManagerFactory.class;
		this.entityManagerInterface = org.hibernate.jpa.HibernateEntityManager.class;
	}

5.创建EntityManagerFactoryBuilder,会注入jpaVendorAdapter,persistenceUnitManager

	@Bean
	@ConditionalOnMissingBean
	public EntityManagerFactoryBuilder entityManagerFactoryBuilder(JpaVendorAdapter jpaVendorAdapter,
			ObjectProvider<PersistenceUnitManager> persistenceUnitManager,
			ObjectProvider<EntityManagerFactoryBuilderCustomizer> customizers) {
		EntityManagerFactoryBuilder builder = new EntityManagerFactoryBuilder(jpaVendorAdapter,
				this.properties.getProperties(), persistenceUnitManager.getIfAvailable());
		customizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
		return builder;
	}

6.创建LocalContainerEntityManagerFactoryBean,这个是实体管理器工厂类的工厂BEAN,用来创建实体管理器工厂对象的。

	@Bean
	@Primary
	@ConditionalOnMissingBean({ LocalContainerEntityManagerFactoryBean.class, EntityManagerFactory.class })
	public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder factoryBuilder) {
		Map<String, Object> vendorProperties = getVendorProperties();
		customizeVendorProperties(vendorProperties);
		return factoryBuilder.dataSource(this.dataSource).packages(getPackagesToScan()).properties(vendorProperties)
				.mappingResources(getMappingResources()).jta(isJta()).build();
	}

 具体的创建这个对象代码,

org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder.Builder.build方法,用来创建实体管理器工厂类的工厂BEAN。
	public LocalContainerEntityManagerFactoryBean build() {
			LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
			if (EntityManagerFactoryBuilder.this.persistenceUnitManager != null) {
				entityManagerFactoryBean
						.setPersistenceUnitManager(EntityManagerFactoryBuilder.this.persistenceUnitManager);
			}
			if (this.persistenceUnit != null) {
				entityManagerFactoryBean.setPersistenceUnitName(this.persistenceUnit);
			}
			entityManagerFactoryBean.setJpaVendorAdapter(EntityManagerFactoryBuilder.this.jpaVendorAdapter);
			entityManagerFactoryBean.setDataSource(this.dataSource);
			entityManagerFactoryBean.setPackagesToScan(this.packagesToScan);
			return entityManagerFactoryBean;
		}

 

7.在实体管理器工厂属性设置回调afterPropertiesSet方法中,会构建本地工厂buildNativeEntityManagerFactory。最终构建的工厂对象为org.hibernate.internal.SessionFactoryImpl

    public SessionFactory build() {
        this.metadata.validate();
        StandardServiceRegistry serviceRegistry = this.metadata.getMetadataBuildingOptions().getServiceRegistry();
        BytecodeProvider bytecodeProvider = (BytecodeProvider)serviceRegistry.getService(BytecodeProvider.class);
        this.addSessionFactoryObservers(new SessionFactoryObserverForBytecodeEnhancer(bytecodeProvider));
        return new SessionFactoryImpl(this.metadata, this.buildSessionFactoryOptions(), HQLQueryPlan::new);
    }
 

 

五、实例化DAO对象的流程

  1.缺省的DAO对象所映射的实体类为org.springframework.data.jpa.repository.support.

SimpleJpaRepository代理对象。

	public SimpleJpaRepository(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {

		Assert.notNull(entityInformation, "JpaEntityInformation must not be null!");
		Assert.notNull(entityManager, "EntityManager must not be null!");

		this.entityInformation = entityInformation;
		this.em = entityManager;
		this.provider = PersistenceProvider.fromEntityManager(entityManager);
	}

 2.这个类依赖EntityManager,所以会接着创建实体管理器对象。这个实体管理器对象所映射的工厂方法为public static javax.persistence.EntityManager org.springframework.orm.jpa.SharedEntityManagerCreator.createSharedEntityManager(javax.persistence.EntityManagerFactory),这个实际上是一个实体管理器的Jdk动态代理对象。

	public static EntityManager createSharedEntityManager(EntityManagerFactory emf, @Nullable Map<?, ?> properties,
			boolean synchronizedWithTransaction, Class<?>... entityManagerInterfaces) {

		ClassLoader cl = null;
		if (emf instanceof EntityManagerFactoryInfo) {
			cl = ((EntityManagerFactoryInfo) emf).getBeanClassLoader();
		}
		Class<?>[] ifcs = new Class<?>[entityManagerInterfaces.length + 1];
		System.arraycopy(entityManagerInterfaces, 0, ifcs, 0, entityManagerInterfaces.length);
		ifcs[entityManagerInterfaces.length] = EntityManagerProxy.class;
		return (EntityManager) Proxy.newProxyInstance(
				(cl != null ? cl : SharedEntityManagerCreator.class.getClassLoader()),
				ifcs, new SharedEntityManagerInvocationHandler(emf, properties, synchronizedWithTransaction));
	}

3.这个动态代理对象包装了实体管理器工厂对象,然后使用工厂对象创建具体的实体管理器,也可以去接口做不同的转发。这里的targetFactory=org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean,也就是JPA初始化时生成的工厂对象。

	private static class SharedEntityManagerInvocationHandler implements InvocationHandler, Serializable {

		private final EntityManagerFactory targetFactory;

		public SharedEntityManagerInvocationHandler(
				EntityManagerFactory target, @Nullable Map<?, ?> properties, boolean synchronizedWithTransaction) {

			this.targetFactory = target;
			this.properties = properties;
			this.synchronizedWithTransaction = synchronizedWithTransaction;
			initProxyClassLoader();
		}

4.接着初始化JpaRepositoryFactoryBean类,此类为工厂类(在创建具体的容器对象前首先要实例化工厂类,这是SPRING的知识,不再详解),后面实例化DAO对象,就是调用此类的getObject方法。这个对象创建后,会调用此类的afterPropertiesSet,最终会调用

SessionFactoryImpl.createEntityManager方法

RepositoryFactoryBeanSupport.afterPropertiesSet
public void afterPropertiesSet() {

		this.factory = createRepositoryFactory();
	
		RepositoryFragments customImplementationFragment = customImplementation //
				.map(RepositoryFragments::just) //
				.orElseGet(RepositoryFragments::empty);

		RepositoryFragments repositoryFragmentsToUse = this.repositoryFragments //
				.orElseGet(RepositoryFragments::empty) //
				.append(customImplementationFragment);
		this.repository = Lazy.of(() -> this.factory.getRepository(repositoryInterface, repositoryFragmentsToUse));

		if (!lazyInit) {
			this.repository.get();
		}
	}

最终创建的factory属性中,有实体管理器,和几个拦截器,用来拦截处理@QUERY,等注解的方法。

 5.重点讲下这里面创建RepositoryFactoryBeanSupport(JpaRepositoryFactoryBean继承于他)的属性repository的生成。由于非懒加载,所以会初始化实例。

public <T> T getRepository(Class<T> repositoryInterface, RepositoryFragments fragments) {

		if (LOG.isDebugEnabled()) {
			LOG.debug("Initializing repository instance for {}…", repositoryInterface.getName());
		}

		Object target = getTargetRepository(information);

		// Create proxy
		ProxyFactory result = new ProxyFactory();
		result.setTarget(target);
		result.setInterfaces(repositoryInterface, Repository.class, TransactionalProxy.class);

		if (MethodInvocationValidator.supports(repositoryInterface)) {
			result.addAdvice(new MethodInvocationValidator());
		}

		result.addAdvisor(ExposeInvocationInterceptor.ADVISOR);
		result.addAdvice(new QueryExecutorMethodInterceptor(information, projectionFactory, queryLookupStrategy,
				namedQueries, queryPostProcessors));

		composition = composition.append(RepositoryFragment.implemented(target));
		result.addAdvice(new ImplementationMethodExecutionInterceptor(composition));

		T repository = (T) result.getProxy(classLoader);

		if (LOG.isDebugEnabled()) {
			LOG.debug("Finished creation of repository instance for {}.", repositoryInterface.getName());
		}

		return repository;
	}

这里的target就是simpleJpaResposity

 

 最终生成的代理对象为这样,包含实体对象,拦截器对象,实现接口等。

 repository为一个JDK的动态代理对象,包装的就 是上面的result,spring的ProxyFactory。

6.最终容器的依赖注入DAO对象,就是调用上面工厂类的getObject方法。也就是返回上面的JDK代理对象。

	public T getObject() {
		return this.repository.get();
	}

 

 六、DAO层接口调用的流程

1.看CONTROLLER的DAO字段属性,可以看到就是上文生成的代理对象。

2.由于我们的DAO层此方法这样写的

@Query(value = "select a.* from fanli_mingxi_new a where a.relate_id=?1 ",nativeQuery = true)
public List<UserMingxi> getUserMingxiByRelate_id(int relate_id);

所以会由QueryExecutorMethodInterceptor来进行处理。

QueryExecutorMethodInterceptor.doInvoke方法中,就会根据queries查找对应的实体查询对象。

private Object doInvoke(MethodInvocation invocation) throws Throwable {

		Method method = invocation.getMethod();

		if (hasQueryFor(method)) {

			QueryMethodInvoker invocationMetadata = invocationMetadataCache.get(method);

			if (invocationMetadata == null) {
				invocationMetadata = new QueryMethodInvoker(method);
				invocationMetadataCache.put(method, invocationMetadata);
			}

			RepositoryQuery repositoryQuery = queries.get(method);
			return invocationMetadata.invoke(repositoryQuery, invocation.getArguments());
		}

		return invocation.proceed();
	}

 可以看到em也是上文创建的JPA代理对象,内部封装了 factory [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean,最终通过持久层调用hibernate的sessionFactoryImpl去创建session(继承了entityManager)

 3.然后调用到em.createNativeQuery(queryString, type),最终映射到

SharedEntityManagerInvocationHandler类的反射调用去创建本地查询 。

 4.创建完查询后,就开始执行查询,然后就调用到hibernate的查询逻辑,查询完返回结果。

七、原生的调用entityManager来创建查询的流程

1.同上面DAO创建流程基本一样,只是少了拦截器转换为entityManager的流程。实际上DAO层的封装,也只是通过拦截器转发到实体管理器进行本地查询。

public class UserMingXiService {

    private EntityManager entityManager;


    private EntityManagerFactory entityManagerFactory;

    public UserMingXiService(EntityManager entityManager, EntityManagerFactory entityManagerFactory) {
        this.entityManager = entityManager;
        this.entityManagerFactory = entityManagerFactory;
    }

    public List<UserMingxi> getMingXiList(int mingxiId){
        Query query = entityManager.createNativeQuery("select a.* from fanli_mingxi_new a where a.relate_id=" + mingxiId);
        List<UserMingxi> userMingxiList = query.getResultList();
        return  userMingxiList;
    }
}

创建的本地查询和前文一样。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot集成JPA是一种常用的开发方式,可以方便地使用JPA来操作数据库。通过引入相应的依赖项,可以实现Spring BootJPA的整合。具体步骤如下: 1. 在项目的pom.xml文件中添加以下依赖项: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> ``` 2. 在application.properties或application.yml配置文件中配置数据库连接信息,如数据库URL、用户名、密码等。 3. 创建实体类,使用JPA注解标注实体类和字段,以映射到数据库表和字段。 4. 创建Repository接口,继承自JpaRepository,可以直接使用Spring Data JPA提供的方法,无需手动编写SQL语句。 5. 在业务逻辑层或控制层中使用Repository接口,调用相应的方法进行数据库操作。 总结起来,通过引入相应的依赖项,配置数据库连接信息,创建实体类和Repository接口,即可实现Spring Boot集成JPA。这样就可以方便地进行数据库操作,提高开发效率。 需要注意的是,JPA是Java Persistence API的简称,是一种ORM(Object-Relational Mapping)框架,可以实现Java对象与数据库表之间的映射,简化了数据库操作的编写。Spring Boot集成JPA可以更加便捷地进行数据库操作,对于新手来说是一个很好的学习实践。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [springboot 集成jpa案例](https://download.csdn.net/download/wu_213616/12506883)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [springboot整合JPA](https://blog.csdn.net/weixin_44740485/article/details/124904112)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [SpringBoot集成JPA](https://blog.csdn.net/csdnerM/article/details/121873780)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值