2012-09-14 6 views
11

... senza in realtà la lettura e l'analisi del persistence.xmlCome recuperare l'origine dati utilizzata da un'unità di persistenza di programmazione

posso recuperare il nome dell'unità di persistenza di un EntityManager utilizzando il properties of it's factory. Posso recuperare le origini dati disponibili usando lo jboss-as-controller-client. Ma non ho trovato alcuna API che mi avrebbe dato l'origine dati di un particolare EntityManager.

Un String con un nome sarebbe sufficiente.

Grazie

Sto lavorando con Hibernate 4.0.1.Final sopra JPA 2 su una JBoss 7.1.1.Final.

EDIT: e vorrei evitare di allontanarsi da APP a Hibernate API, se possibile.

EDIT: la soluzione di Augusto lavorato, ho alcuni appunti sui dettagli: Il casting del EM non ha funzionato a causa di un ClassCastException :(org.jboss.as.jpa.container.TransactionScopedEntityManager cannot be cast to org.hibernate.ejb.EntityManagerImpl), ma ha funzionato per la fabbrica recuperata. Così ho omesso il passaggio 1.

anche io non sono riuscito a trovare un modo per recuperare il nome dell'origine dati dall'istanza. Così ho dovuto accontentarmi il nome del catalogo: connectionProvider.getConnection().getCatalog();

risposta

14

è necessario:

  1. scagli la EntityManager al EntityManagerImpl (l'implementazione Hibernate)
  2. chiamata getFactory()
  3. cast del EntityManagerFactory a HibernateEntityManagerFactory
  4. chiamare getSessionFactory() e trasmetterlo a SessionFactoryImpl
  5. chiama getConnectionProvider() e lanciatelo sull'implementazione corretta. Puoi vedere le implementazioni here. Suppongo che sia un
  6. chiamare getDataSource() e il gioco è fatto.

Sfortunatamente, è necessario utilizzare l'API di Hibernate, poiché non è possibile recuperare DataSource utilizzando l'API JPA.

+0

Grazie, Augusto, sembra promettente. Sto ancora lottando per uscire dall'inferno della dipendenza, cercando di scoprire quali artefatti in letargo jboss in realtà fornisce loro riferimento nel mio pom. Accetterò una volta che vedo la luce – kostja

+0

lavorata, con alcune stranezze però. Vedere la domanda modificata – kostja

+3

Un altro attacco contro l'APP a mio parere ... Questo processo, sebbene corretto, è molto più complicato del necessario. – rtcarlson

8

Se si desidera solo il nome del DataSource e che il nome di origine dati sono stati forniti per mezzo JPA, si dovrebbe essere in grado di ottenere tali informazioni tramite:

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

o

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

seconda come hai definito l'origine dati.

+1

Non funziona per me :(entrambe le query restituiscono 'null'. Ti capita di avere una fonte per questi nomi di proprietà? – kostja

+0

Una fonte? Non sei sicuro di cosa intendi. La specifica JPA li definisce. È questo che intendi? –

+0

Sì, ho pensato di provare altre proprietà: ho trovato il punto - §9.4.3 Proprietà dell'unità di persistenza. Come ho capito, poiché l'impostazione di queste proprietà non è richiesta, potrebbero rimanere non impostate dal provider. caso per Hibernate? – kostja

4

Avevo bisogno di fare questo per poter eseguire le migrazioni Flyway.Non ero in grado di recuperare il DataSource utilizzando il metodo di Augusto, ma sono stato in grado di ricreare l'origine dati recuperando l'URL, il nome utente & la password dalle proprietà 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"); 
+0

cool, questo potrebbe essere l'aggiornamento/correzione promesso. – kostja

+0

No, no. L'utilizzo di un diverso 'DataSource' (anche indicando lo stesso database) può portare a problemi molto sottili. –

5

In un ambiente di primavera è possibile utilizzare questo :

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

@PersistenceContext 
EntityManager entityManager; 

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

Prova questa:

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

Questo ha funzionato per me. Tks –

1

sto usando Hibernate 5.0.x

Ecco come sto diventando una connessione dal pool di persistenza:

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

Il parametro emf è standard javax.persistence.EntityManagerFactory dell'APP, tipicamente acquisito a livello globale utilizzando:

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

o per iniezione:

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