简体   繁体   English

Spring Boot不会在状态表上建立JPA数据库连接

[英]Spring Boot NOT to make JPA database connection on statup

I have a Spring Boot + Groovy application that requires the Database Connection to be made per-session or per-tenant basis. 我有一个Spring Boot + Groovy应用程序,它要求按会话或按租户建立数据库连接。 When implementing the solution using Hibernate only it works, however when adding spring-boot-starter-data-jpa and switching to JPA a database connection is attempted on start up which fails because there is no connection settings defined yet. 当使用Hibernate实现解决方案时,它只能工作,但是当添加spring-boot-starter-data-jpa并切换到JPA时,尝试在启动数据库连接,但由于尚未定义连接设置而失败。

I have a gradle dependencies block that looks like this: 我有一个gradle依赖项块,看起来像这样:

dependencies {
    compile "org.springframework.boot:spring-boot-starter-web"
    compile "org.springframework.boot:spring-boot-starter-data-jpa"

    compile "org.codehaus.groovy:groovy-all:2.3.3"

    compile "org.springframework:spring-core:${springVersion}"
    compile "org.springframework:spring-webmvc:${springVersion}"
    compile "org.springframework:spring-orm:${springVersion}"
    compile "org.springframework:spring-aop:${springVersion}"
    compile "org.springframework:spring-context-support:${springVersion}"
    compile "org.hibernate:hibernate-entitymanager:${hibernateVersion}"
    compile "com.oracle:ojdbc7:12.1.0.1"
    compile "org.apache.commons:commons-dbcp2:2.0.1"
    compile "cglib:cglib:3.1"
...
}

And my Application.groovy looks like this: 我的Application.groovy看起来像这样:

@Configuration
@EnableAutoConfiguration
@ComponentScan
@EnableTransactionManagement
class Application
{
    final Logger aLog = Logger.getLogger(Application.class)

    @Autowired
    DatabaseSettings dbSettings

    @Bean(destroyMethod="close")
    @Lazy
    public DataSource dataSource()
    {
        aLog.info ">>>>>>>>>>>>> CREATING DATA SOURCE <<<<<<<<<<<<<<<"
        new BasicDataSource(driverClassName: dbSettings.driverClassName,    
                            url: dbSettings.dbUrl, username: dbSettings.dbUser, password: dbSettings.dbPass, 
                            maxTotal: 10, maxWaitMillis: 10000, maxIdle:10, defaultAutoCommit:false)
    }

    @Bean
    @Lazy
    public LocalContainerEntityManagerFactoryBean entityManagerFactory()
    {
        Properties hqlProps =   ['hibernate.dialect': this.dbSettings.dialect, 'hibernate.temp.use_jdbc_metadata_defaults': false,
                                 'hibernate.show_sql': this.dbSettings.showSql, 'hibernate.format_sql': this.dbSettings.formatSql, 
                                 'hibernate.use_sql_comments': this.dbSettings.useSqlComments] as Properties

        aLog.info ">>>>>>>>>>>>> CREATING ENTITY MANAGER FACTORY <<<<<<<<<<<<<<<"

        LocalContainerEntityManagerFactoryBean em   =   new LocalContainerEntityManagerFactoryBean()

        em.setDataSource(dataSource())
        em.setPackagesToScan(this.dbSettings.getPackagesToScan())
        em.setJpaVendorAdapter(new HibernateJpaVendorAdapter())
        em.setJpaProperties(hqlProps)
        em
    }

    @Bean
    @Lazy
    public JpaTransactionManager transactionManager()
    {
        aLog.info ">>>>>>>>>>>>> CREATING TRANSACTION MANAGER <<<<<<<<<<<<<<<"
        new JpaTransactionManager(entityManagerFactory: entityManagerFactory().getObject())     
    }

    static void main(args) throws Exception
    {
        ApplicationContext appCtx = SpringApplication.run(Application.class, args)
    }
}

I have removed the Scopes configuration for simplicity. 为了简单起见,我删除了Scopes配置。

The point is that all relevant Beans are annotated as @Lazy, however at start up I see the messages regarding the Data Source and Entity Manager being created. 关键是所有相关的Bean都标注为@Lazy,但是在启动时,我看到有关正在创建的数据源和实体管理器的消息。

Debugging the code looks like at some point HibernateJpaAutoConfigurer is called and this class have @Autowired the DataSource in thus causing the instantiation of these beans on start up. 调试代码看起来像在某个时候调用了HibernateJpaAutoConfigurer,并且此类已经@Autowired了DataSource,从而导致这些bean在启动时实例化。

My question is: How can I prevent Spring Boot to attempt a Database Connection on start up? 我的问题是:如何防止Spring Boot在启动时尝试进行数据库连接?

Thanks in advance 提前致谢

I think I found a work around: 我想我找到了一种解决方法:

Looking at spring-boot-starte-data-jpa's pom.xml I found that it depends on spring-data-jpa, so I decided to replace the starter-data-jpa with just spring-data-jpa with partial results. 通过查看spring-boot-starte-data-jpa的pom.xml,我发现它依赖于spring-data-jpa,因此我决定仅将springer-data-jpa替换为starter-data-jpa,并得到部分结果。 Still I couldn't get session scopes or custom scopes to delay the initialization of components, it wouldn't even compile actually. 仍然我无法获得会话作用域或自定义作用域来延迟组件的初始化,它甚至无法实际编译。 So in order to get everything to work nice I needed to all aspectjweaver too. 因此,为了使一切正常工作,我也需要所有aspectjweaver。

So now my dependencies look like: 所以现在我的依赖项看起来像:

dependencies {
compile "org.springframework.boot:spring-boot-starter-web"
// 
compile "org.springframework.data:spring-data-jpa:1.7.1.RELEASE"
compile "org.aspectj:aspectjweaver:1.8.4"

compile "org.codehaus.groovy:groovy-all:2.3.3"
... }

So, if now I annotate DataSource creation with @Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS) or even with a Custom Scope, the instantiation happens after the startup process, as expected. 因此,如果现在我使用@Scope(value =“ session”,proxyMode = ScopedProxyMode.TARGET_CLASS或什至使用Custom Scope注释数据源的创建,则实例化将在启动过程之后如期进行。

However it feels like defeating the purpose of using SpringBoot, I still think there should be a way to configure SpringBoot in such a way that I can achieve same results. 但是,这感觉像击败了使用SpringBoot的目的,我仍然认为应该有一种方法可以配置SpringBoot,使我可以达到相同的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM