it-swarm.com.de

So rufen Sie die von einer Persistenzeinheit verwendete Datenquelle programmgesteuert ab

... ohne den persistence.xml wirklich zu lesen und zu parsen

Ich kann den Namen der Persistenzeinheit einer EntityManager mithilfe der -Eigenschaften der Factory abrufen. Ich kann die verfügbaren Datenquellen mit dem jboss-as-controller-client abrufen. Ich habe jedoch keine API gefunden, die mir die Datenquelle einer bestimmten EntityManager gibt.

Eine String mit einem Namen würde ausreichen.

Vielen Dank

Ich arbeite mit Hibernate 4.0.1.Final über JPA 2 an einem JBoss 7.1.1.Final.

BEARBEITEN: und ich möchte möglichst nicht von JPA zu Hibernate-APIs wechseln.

EDIT: Augustos Lösung hat funktioniert, ich habe ein paar Anmerkungen zu Details: Das Casting des EM funktionierte aufgrund einer ClassCastException: (org.jboss.as.jpa.container.TransactionScopedEntityManager cannot be cast to org.hibernate.ejb.EntityManagerImpl) nicht, aber es funktionierte für die abgerufene Fabrik. Also habe ich Schritt 1 weggelassen.

Ich konnte auch keinen Weg finden, um den Namen der Datenquelle aus der Instanz abzurufen. Also musste ich mich mit dem Katalognamen zufrieden geben: connectionProvider.getConnection().getCatalog();

17
kostja

Du musst:

  1. gib die EntityManager in EntityManagerImpl (die Hibernate-Implementierung)
  2. rufen Sie getFactory() an
  3. gib das EntityManagerFactory in HibernateEntityManagerFactory
  4. rufe getSessionFactory() auf und gib es in SessionFactoryImpl
  5. rufen Sie getConnectionProvider() auf und wandeln Sie es in die richtige Implementierung um. Sie können die Implementierungen hier sehen. Ich gehe davon aus, dass es eine DatasourceConnectionProvider ist.
  6. rufen Sie getDataSource() auf und Sie sind fertig.

Leider müssen Sie die Hibernate-API verwenden, da es keine Möglichkeit gibt, die DataSource mithilfe der JPA-API abzurufen.

19
Augusto

Wenn Sie nur möchten, dass der Name der Datenquelle und der Name der Datenquelle mit JPA-Mitteln angegeben wurde, sollten Sie diese Informationen abrufen können:

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

oder

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

abhängig davon, wie Sie die Datenquelle definiert haben.

8
Steve Ebersole

In einer Spring-Umgebung können Sie Folgendes verwenden:

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

@PersistenceContext
EntityManager entityManager;

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

Ich musste dies tun, um Flyway-Migrationen durchzuführen. Ich konnte die DataSource nicht mit der Methode von Augusto abrufen, aber ich konnte die Datenquelle durch das Abrufen der URL, des Benutzernamens und des Kennworts aus den SessionFactory-Eigenschaften wiederherstellen:

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

Versuche dies :

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();

Ich verwende Hibernate 5.0.x

So bekomme ich eine Verbindung aus dem Persistenzpool:

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();
}

Der Parameter emf ist der Standard javax.persistence.EntityManagerFactory von JPA.

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

oder durch Injektion:

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

Das hat mir geholfen. Ich benutze HikariCP, aber ich glaube nicht, dass es wichtig ist.

Grundsätzlich muss getan werden 

  1. finden Sie eine Service-Registry
  2. dienst von org.hibernate.engine.jdbc.connections.spi.ConnectionProvider-Klasse abrufen
  3. packen Sie es in javax.sql.DataSource aus.

Die Service-Registry kann von EntityManager abgerufen werden

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

oder direkt von EntityManagerFactory

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

Ich verwende Hibernate 5.2.10.Final und Folgendes hat für mich gearbeitet:

    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);
    }

Sie müssen nur entityManager.getEntityManagerFactory () an diese Methode übergeben (In meinem Fall habe ich mehrere Fabriken. Dann kann ich diese Methode verwenden, um bei Bedarf die Datenquelle abzurufen.).

0
Youness