在 Micronaut + Hibernate 中以编程方式为 Heroku Postgres 设置数据源

setting DataSource programmatically in Micronaut + Hibernate for Heroku Postgres

我有一个要部署到 Heroku 上的应用程序。 Heroku 会不时更新数据库凭据,它们会自动将连接配置注入到一个环境变量中。这个环境变量可以解析得到用户、密码和URL.

我尝试按照他们推荐的方式进行数据源配置。

@Factory
//@Requires(env = Environment.HEROKU)
public class HerokuDataSourceConfig {

    @Bean
    public DataSource dataSource() throws URISyntaxException {
//        URI dbUri = new URI(System.getenv("DATABASE_URL"));

//        String username = dbUri.getUserInfo().split(":")[0];
//        String password = dbUri.getUserInfo().split(":")[1];
//        String dbUrl = "jdbc:postgresql://" + dbUri.getHost() + ':' + dbUri.getPort() + dbUri.getPath() + "?sslmode=require";

        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:postgresql://localhost:5432/postgres");
        config.setUsername("postgres");
        config.setPassword("");
        config.setDriverClassName("org.postgresql.Driver");
        config.setConnectionTestQuery("SELECT 1");

        return new HikariUrlDataSource(config);
    }
}

注释行来自初始 heroku 配置,未注释的代码仅用于本地测试。

当我尝试 运行 应用程序并访问需要 Hibernate 的端点时,我得到了这个

No bean of type [javax.persistence.EntityManager] exists. Make sure the bean is not disabled by bean requirements (enable trace logging for 'io.micronaut.context.condition' to check) and if the bean is enabled then ensure the class is declared a bean and annotation processing is enabled (for Java and Kotlin the 'micronaut-inject-java' dependency should be configured as an annotation processor).

我按照建议激活了跟踪,这里是一些相关的日志数据

20:24:50.414 [pool-1-thread-15] DEBUG i.m.context.condition.Condition - Bean [Definition: io.micronaut.configuration.hibernate.jpa.EntityManagerFactoryBean] will not be loaded due to failing conditions:
20:24:50.414 [pool-1-thread-15] DEBUG i.m.context.condition.Condition - * No bean of type [interface org.hibernate.boot.SessionFactoryBuilder] present within context
20:28:04.598 [main] DEBUG i.m.context.condition.Condition - Bean [Definition: io.micronaut.jdbc.spring.DataSourceTransactionManagerFactory] will not be loaded due to failing conditions:
20:28:04.599 [main] DEBUG i.m.context.condition.Condition - * Custom condition [class io.micronaut.jdbc.spring.HibernatePresenceCondition] failed evaluation
20:28:04.895 [main] DEBUG i.m.context.condition.Condition - Bean [Definition: io.micronaut.configuration.hibernate.jpa.EntityManagerFactoryBean] will not be loaded due to failing conditions:
20:28:04.895 [main] DEBUG i.m.context.condition.Condition - * No bean of type [class org.hibernate.boot.MetadataSources] present within context
20:28:04.895 [main] DEBUG i.m.context.condition.Condition - Bean [Definition: io.micronaut.configuration.hibernate.jpa.EntityManagerFactoryBean] will not be loaded due to failing conditions:
20:28:04.896 [main] DEBUG i.m.context.condition.Condition - * No bean of type [interface org.hibernate.boot.SessionFactoryBuilder] present within context

我做错了什么?可能配置很好,但不知何故 Micronaut 不知道我新配置的数据源。

当我调试这段代码时,当 micronaut 启动时,它会在某个时候进入工厂并创建数据源。在调用数据源工厂之前打印之前的日志。

仅使用@Bean它是一个重复创建的原型bean。尝试使用:

@Singleton
@Primary
public DataSource dataSource()
...

在此期间,我在 Heroku 的帮助下找到了解决方案。

对于像我这样使用 gradle buildpack 的应用程序,Heroku 将以下环境变量注入到容器中。我一开始没看到那些,我只知道 DATABASE_URL

datasources:
  default:
    url: ${JDBC_DATABASE_URL}
    username: ${JDBC_DATABASE_USERNAME}
    password: ${JDBC_DATABASE_PASSWORD}
    driverClassName: org.postgresql.Driver

很高兴您找到了解决方案。任何状况之下。我们可以读取该环境变量并将 DATABASE_URL 拆分为 :,@ 并找到主机、用户名和密码。