How to programmatically discover the JPA implementation and SQL dialect being used by Spring Boot?

时间:2019-04-17 00:38:04

标签: java spring spring-boot spring-data-jpa spring-jdbc

I know it is possible to change the JPA implementation in use by Spring Boot, the default is to use Hibernate, but it's also possible to user others, like EclipseLink. It is possible to find, at application runtime, which JPA implementation is being used, and also discover which SQL dialect is currently in use (like MySQL, PostgreSQL, Oracle)?

3 个答案:

答案 0 :(得分:2)

如@Prabin所述,如果您有权访问应用程序日志,则应该能够使用grep进行“方言”,并且不使用JPA供应商和方言。

2019-04-17 02:02:55.061  INFO 12724 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.SQLServer2012Dialect

如果您有权访问代码,则更简单的操作就是查看配置,但是由于您询问了程序确定,因此您可以做几件事(假设您可以在自己的程序中访问Spring Beans)通过ApplicationContext或通过注入)。

使用ApplicationContext访问JpaVendorAdapter Bean,我可以确定我的JPA供应商是org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter,但是方言详细信息的用处不大:

public static void main( String[] args ) {
        SpringApplication springApplication = new SpringApplication( DevicePeersApplication.class );
        ConfigurableApplicationContext appContext = springApplication.run( args );
        JpaVendorAdapter jpaVendorAdapter = appContext.getBean( JpaVendorAdapter.class );
        log.debug( "JPA Vendor Adapter: {}", jpaVendorAdapter.getClass().getName() );
        log.debug( "JPA Dialect: {}", jpaVendorAdapter.getJpaDialect().getClass().getName() );
        ...
}

2019-04-17 02:02:59.226 DEBUG 12724 --- [           main] c.c.n.d.Application           : JPA Vendor Adapter: org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter
2019-04-17 02:02:59.226 DEBUG 12724 --- [           main] c.c.n.d.Application           : JPA Dialect: org.springframework.orm.jpa.vendor.HibernateJpaDialect

在知道JpaVendorAdapterorg.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter的情况下,我现在知道,对您感兴趣的EntityManagerFactory上的属性将以hibernate.为前缀特别是hibernate.dialect。您将必须查找替代JPA实现的细节,例如EclipseLink。

EntityManagerFactory entityManagerFactory = appContext.getBean( "entityManagerFactory", EntityManagerFactory.class );

String dialect = (String) entityManagerFactory.getProperties().getOrDefault( "hibernate.dialect", "" );

log.debug( "{}={}", "hibernate.dialect", dialect );


2019-04-17 02:02:59.228 DEBUG 12724 --- [           main] c.c.n.d.Application           : hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect

为了完整起见,您可以使用以下命令拉出所有特定于Hibernate的属性,以替换“ hibernate”。以及其他JPA实现所需的另一个属性前缀:

entityManagerFactory
            .getProperties()
            .entrySet()
            .stream()
            .filter( entry -> entry.getKey().startsWith( "hibernate." ) )
            .forEach( entry -> log.debug( entry.toString() ) );

最后,由于JpaVendorAdapterEntityManagerFactory是Spring Bean,因此您可以将它们注入代码的另一部分并在那里进行处理:

@Autowired
JpaVendorAdapter jpaVendorAdapter;

@Autowired
EntityManagerFactory entityManagerFactory;

void myMethod() {
    entityManagerFactory.getProperties()...
}

答案 1 :(得分:1)

您可以浏览AutowireCapableBeanFactory。您可以获取JpaBaseConfiguration.class bean。然后检查jpaVendorAdapter和jpaDialect。那可能行得通。这是@RestController的示例。

@RestController
class JpaConfigResource {

  @Autowired
  private ApplicationContext applicationContext;

  @RequestMapping("/jpa")
  Map<String, String> getJpaConfig() {

    JpaBaseConfiguration jpaConfig = null;
    String jpaVendorAdapter = "Not Found";
    String jpaDialect = "Not Found";
    Map<String, String> result = new HashMap<>();

    AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getAutowireCapableBeanFactory();

    if (autowireCapableBeanFactory != null) {
      jpaConfig = autowireCapableBeanFactory.getBean(JpaBaseConfiguration.class);
    } else {
      System.out.println("autowireCapableBeanFactory was not found...");
    }

    if (jpaConfig != null) {
      jpaVendorAdapter = jpaConfig.jpaVendorAdapter().getClass().getName();
      jpaDialect = jpaConfig.jpaVendorAdapter().getJpaDialect().getClass().getName();
    } else {
      System.out.println("jpaConfig was not found...");
    }

    result.put("jpaVendorAdapter", jpaVendorAdapter);
    result.put("jpaDialect", jpaDialect);

    System.out.println("result => " + result.toString());

    return result;
  }
}

答案 2 :(得分:1)

另一种可能的解决方案是从application.yml文件中检查JDBC字符串:-)