web-dev-qa-db-fra.com

Comment récupérer la source de données utilisée par une unité de persistance par programme

... sans réellement lire et analyser le persistence.xml

Je peux récupérer le nom de l'unité de persistance d'une EntityManager en utilisant les propriétés de sa fabrique . Je peux récupérer les sources de données disponibles en utilisant le jboss-as-controller-client . Mais je n'ai trouvé aucune API qui me donnerait la source de données d'un EntityManager particulier.

Une String avec un nom suffirait.

Je vous remercie

Je travaille avec Hibernate 4.0.1.Final sur JPA 2 sur un JBoss 7.1.1.Final.

EDIT: et je voudrais éviter, si possible, de s’éloigner des API JPA vers Hibernate.

EDIT: La solution d’Augusto a fonctionné, j’ai quelques remarques sur les détails: Le casting de l’EM n’a pas fonctionné à cause d’une ClassCastException: (org.jboss.as.jpa.container.TransactionScopedEntityManager cannot be cast to org.hibernate.ejb.EntityManagerImpl), mais cela a fonctionné pour l’usine récupérée. J'ai donc omis l'étape 1.

Je ne pouvais pas non plus trouver un moyen de récupérer le nom de la source de données à partir de l'instance. Je devais donc me contenter du nom du catalogue: connectionProvider.getConnection().getCatalog();

17
kostja

Tu dois:

  1. transformez EntityManager en EntityManagerImpl (l'implémentation d'Hibernate)
  2. appeler getFactory()
  3. jette EntityManagerFactory à HibernateEntityManagerFactory
  4. appelez getSessionFactory() et transformez-le en SessionFactoryImpl
  5. appelez getConnectionProvider() et convertissez-le en implémentation correcte. Vous pouvez voir les implémentations ici . Je suppose que c'est une DatasourceConnectionProvider
  6. appelez getDataSource() et vous avez terminé.

Malheureusement, vous devez utiliser l'API Hibernate, car il n'existe aucun moyen de récupérer le DataSource à l'aide de l'API JPA.

19
Augusto

Si vous voulez juste le nom de la source de données et que le nom de la source de données a été fourni par JPA, vous devriez pouvoir obtenir ces informations via:

entityManager.getEntityManagerFactory().getProperties().get( "javax.persistence.jtaDataSource" );

ou

entityManager.getEntityManagerFactory().getProperties().get( "javax.persistence.nonJtaDataSource" );

en fonction de la définition de la source de données.

8
Steve Ebersole

Dans un environnement de printemps, vous pouvez utiliser ceci:

import org.springframework.orm.jpa.EntityManagerFactoryInfo;
...

@PersistenceContext
EntityManager entityManager;

public DataSource getDataSourceFromHibernateEntityManager() {
   EntityManagerFactoryInfo info = (EntityManagerFactoryInfo) entityManager.getEntityManagerFactory();
   return info.getDataSource();
}
6
Markus Umefjord

Je devais le faire pour pouvoir exécuter les migrations Flyway. Je n'ai pas pu récupérer la source de données à l'aide de la méthode d'Augusto, mais j'ai pu recréer la source de données en récupérant l'url, le nom d'utilisateur et le mot de passe à partir des propriétés SessionFactory:

SessionFactory sessionFactory = ((HibernateEntityManagerFactory) entityManagerFactory).getSessionFactory();
Properties properties = ((SessionFactoryImpl) sessionFactory).getProperties();
String url = (String) properties.get("hibernate.connection.url");
String username = (String) properties.get("hibernate.connection.username");
String password = (String) properties.get("hibernate.connection.password");
4
shangxiao

Essaye ça :

Session s = (Session) getEntityManager().getDelegate();
org.hibernate.SessionFactory sessionFactory=s.getSessionFactory();
ConnectionProvider cp=((SessionFactoryImpl)sessionFactory).getConnectionProvider();Connection connection=cp.getConnection();
DatabaseMetaData dbmetadata= connection.getMetaData();
String dtsource=dbmetadata.getUserName();
3

J'utilise Hibernate 5.0.x

Voici comment je reçois une connexion du pool de persistance:

import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.jpa.internal.EntityManagerFactoryImpl;

public Connection getConnection(EntityManagerFactory emf) throws SQLException
{
    final EntityManagerFactoryImpl hibernateEmf = (EntityManagerFactoryImpl) emf;
    return hibernateEmf.getSessionFactory().getServiceRegistry().getService(ConnectionProvider.class).getConnection();
}

Le paramètre emf est le javax.persistence.EntityManagerFactory standard de JPA, généralement acquis de manière globale à l'aide de:

emf = Persistence.createEntityManagerFactory("persistence-unit-name");

ou par injection:

@PersistenceUnit(unitName="persistence-unit-name")
EntityManagerFactory emf;
2
Zach-M

Voici ce qui m'a aidé. J'utilise HikariCP mais je ne pense pas que cela compte.

Fondamentalement, ce qui doit être fait est 

  1. trouver un registre de service
  2. obtenir le service par org.hibernate.engine.jdbc.connections.spi.ConnectionProvider classe
  3. décompressez-le à javax.sql.DataSource.

Le registre de service peut être récupéré à partir de EntityManager

((SessionImpl) em).getFactory().getServiceRegistry()

ou de EntityManagerFactory directement

((SessionFactoryImpl) entityManagerFactory).getServiceRegistry()
0
Mikie Mike

J'utilise hibernate 5.2.10.Final et ce qui suit a fonctionné pour moi:

    import org.hibernate.SessionFactory;
    import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
    import javax.persistence.EntityManagerFactory;
    import javax.sql.DataSource;
    //...
    public static DataSource getDataSource(EntityManagerFactory entityManagerFactory) {
    ConnectionProvider cp = ((SessionFactory) entityManagerFactory).getSessionFactoryOptions()
            .getServiceRegistry()
            .getService(ConnectionProvider.class);
    return cp.unwrap(DataSource.class);
    }

Ce que vous avez besoin est simplement de passer entityManager.getEntityManagerFactory () à cette méthode (dans mon cas, j'ai plusieurs usines. Ensuite, je peux utiliser cette méthode pour obtenir la source de données de l'une d'elles en cas de besoin).

0
Youness