2
votes

Comment découvrir par programme l'implémentation JPA et le dialecte SQL utilisé par Spring Boot?

Je sais qu'il est possible de changer l'implémentation JPA utilisée par Spring Boot, la valeur par défaut est d'utiliser Hibernate, mais il est également possible d'en utiliser d'autres, comme EclipseLink. Il est possible de trouver, lors de l'exécution de l'application, quelle implémentation JPA est utilisée, et également de découvrir quel dialecte SQL est actuellement utilisé (comme MySQL, PostgreSQL, Oracle)?


2 commentaires

Cela dépend de ce que vous entendez par temps d'exécution. Si vous avez accès aux journaux des applications, il peut être possible de trouver les détails.


Vous pouvez donc simplement vérifier le type d'implémentation réel de EntityManager pour déterminer l'implémentation JPA. Et découvrir le dialecte dépend du fournisseur JPA.


3 Réponses :


2
votes

Comme indiqué par @Prabin, si vous avez accès aux journaux de l'application, vous devriez être en mesure de grep pour «dialecte» et de repartir avec le fournisseur JPA et le dialecte en cours d'utilisation.

@Autowired
JpaVendorAdapter jpaVendorAdapter;

@Autowired
EntityManagerFactory entityManagerFactory;

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

Si vous avez accès au code, la chose la plus simple à faire serait simplement de revoir la configuration, mais puisque vous avez posé des questions sur la détermination par programme, vous pouvez faire deux ou trois choses (en supposant que vous puissiez accéder à Spring Beans dans votre code via ApplicationContext ou par injection).

En utilisant le ApplicationContext pour accéder au Bean JpaVendorAdapter , je peux déterminer mon Le fournisseur JPA doit être org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter , mais les détails du dialecte sont moins utiles:

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

Sachant que le JpaVendorAdapter est org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter , je sais maintenant que les propriétés de EntityManagerFactory qui m'intéressent vont être pré corrigé avec hibernate. , dans votre cas spécifiquement hibernate.dialect . Vous devrez rechercher les spécificités des implémentations JPA alternatives comme 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

Pour être complet, vous pouvez extraire toutes les propriétés spécifiques à Hibernate par ce qui suit, en remplaçant «hibernate». avec un autre préfixe de propriété si nécessaire pour d'autres implémentations JPA:

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

Enfin, puisque JpaVendorAdapter et EntityManagerFactory sont des Spring Beans, vous pouvez simplement les injecter dans une autre partie de votre code et les traiter ici:

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


0 commentaires

1
votes

Vous pouvez fouiller dans AutowireCapableBeanFactory. Vous pouvez obtenir le bean JpaBaseConfiguration.class. Vérifiez ensuite le jpaVendorAdapter et le jpaDialect. Cela peut fonctionner. Voici un exemple de @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;
  }
}


0 commentaires

1
votes

Une autre solution possible serait d'inspecter la chaîne JDBC du fichier application.yml :-)