如何以编程方式发现 Spring Boot 使用的 JPA 实现和 SQL 方言?
How to programmatically discover the JPA implementation and SQL dialect being used by Spring Boot?
我知道可以通过 Spring Boot 更改正在使用的 JPA 实现,默认是使用 Hibernate,但也可以使用其他的,比如 EclipseLink。可以在应用程序运行时找到正在使用哪个 JPA 实现,还可以发现当前正在使用哪个 SQL 方言(如 MySQL、PostgreSQL、Oracle)?
如@Prabin 所述,如果您有权访问应用程序日志,您应该能够 grep 查找 'dialect' 并获得正在使用的 JPA 供应商和方言。
2019-04-17 02:02:55.061 INFO 12724 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.SQLServer2012Dialect
如果您有权访问代码,那么更容易做的事情就是查看配置,但是由于您询问了程序化确定,因此您可以做几件事(假设您可以访问 Spring 通过 ApplicationContext
或通过注入在您的代码中添加 Beans)。
使用 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
知道 JpaVendorAdapter
是 org.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 的属性,根据其他 JPA 实现的需要将 'hibernate.' 替换为另一个 属性 前缀:
entityManagerFactory
.getProperties()
.entrySet()
.stream()
.filter( entry -> entry.getKey().startsWith( "hibernate." ) )
.forEach( entry -> log.debug( entry.toString() ) );
最后,由于 JpaVendorAdapter
和 EntityManagerFactory
是 Spring Beans,您可以将它们注入代码的另一部分并在那里处理它们:
@Autowired
JpaVendorAdapter jpaVendorAdapter;
@Autowired
EntityManagerFactory entityManagerFactory;
void myMethod() {
entityManagerFactory.getProperties()...
}
您可以深入了解 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;
}
}
另一种可能的解决方案是检查 application.yml 文件中的 JDBC 字符串:-)
我知道可以通过 Spring Boot 更改正在使用的 JPA 实现,默认是使用 Hibernate,但也可以使用其他的,比如 EclipseLink。可以在应用程序运行时找到正在使用哪个 JPA 实现,还可以发现当前正在使用哪个 SQL 方言(如 MySQL、PostgreSQL、Oracle)?
如@Prabin 所述,如果您有权访问应用程序日志,您应该能够 grep 查找 'dialect' 并获得正在使用的 JPA 供应商和方言。
2019-04-17 02:02:55.061 INFO 12724 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.SQLServer2012Dialect
如果您有权访问代码,那么更容易做的事情就是查看配置,但是由于您询问了程序化确定,因此您可以做几件事(假设您可以访问 Spring 通过 ApplicationContext
或通过注入在您的代码中添加 Beans)。
使用 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
知道 JpaVendorAdapter
是 org.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 的属性,根据其他 JPA 实现的需要将 'hibernate.' 替换为另一个 属性 前缀:
entityManagerFactory
.getProperties()
.entrySet()
.stream()
.filter( entry -> entry.getKey().startsWith( "hibernate." ) )
.forEach( entry -> log.debug( entry.toString() ) );
最后,由于 JpaVendorAdapter
和 EntityManagerFactory
是 Spring Beans,您可以将它们注入代码的另一部分并在那里处理它们:
@Autowired
JpaVendorAdapter jpaVendorAdapter;
@Autowired
EntityManagerFactory entityManagerFactory;
void myMethod() {
entityManagerFactory.getProperties()...
}
您可以深入了解 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;
}
}
另一种可能的解决方案是检查 application.yml 文件中的 JDBC 字符串:-)