How to retrieve the datasource used by a persistence unit programmatically
Solution 1
You need to:
- cast the
EntityManager
toEntityManagerImpl
(the Hibernate implementation) - call
getFactory()
- cast the
EntityManagerFactory
toHibernateEntityManagerFactory
- call
getSessionFactory()
and cast it toSessionFactoryImpl
- call
getConnectionProvider()
and cast it to the correct implementation. You can see the implementations here. I'll assume that it's aDatasourceConnectionProvider
- call
getDataSource()
and you're done.
Unfortunately, you must use the Hibernate API, as there's no way to retrieve the DataSource using the JPA API.
Solution 2
In a Spring environment you can use this:
import org.springframework.orm.jpa.EntityManagerFactoryInfo;
...
@PersistenceContext
EntityManager entityManager;
public DataSource getDataSourceFromHibernateEntityManager() {
EntityManagerFactoryInfo info = (EntityManagerFactoryInfo) entityManager.getEntityManagerFactory();
return info.getDataSource();
}
Solution 3
If you just want the name of the datasource and that datasource name was supplied per JPA means, you should be able to get that information via:
entityManager.getEntityManagerFactory().getProperties().get( "javax.persistence.jtaDataSource" );
or
entityManager.getEntityManagerFactory().getProperties().get( "javax.persistence.nonJtaDataSource" );
depending on how you defined the datasource.
Solution 4
I am using hibernate 5.2.10.Final and the following worked for me:
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);
}
What you need is just to pass entityManager.getEntityManagerFactory() to this method (For my case, I have multiple factories. Then I can use this method to get the datasource for any of them when needed).
Solution 5
I needed to do this in order to run Flyway migrations. I wasn't able to retrieve the DataSource using Augusto's method, but I was able to recreate the data source by retrieving the url, username & password from the SessionFactory properties:
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");
kostja
We are here to learn :) Works and plays with scala, kafka, data, linux
Updated on June 13, 2021Comments
-
kostja almost 3 years
...without actually reading and parsing the
persistence.xml
I can retrieve the name of the persistence unit of an
EntityManager
using the properties of it's factory. I can retrieve the available datasources using the jboss-as-controller-client. But I have found no API that would give me the datasource of a particularEntityManager
.A
String
with a name would be enough.Thank you
I am working with Hibernate 4.0.1.Final over JPA 2 on a JBoss 7.1.1.Final.
EDIT: and I would like to avoid straying from JPA to Hibernate APIs if possible.
EDIT : Augusto's solution worked, I have some notes on details: The casting of the EM didn't work because of a
ClassCastException
:(org.jboss.as.jpa.container.TransactionScopedEntityManager cannot be cast to org.hibernate.ejb.EntityManagerImpl
), but it worked for the retrieved factory. So I omitted step 1.I also could not find a way to retrieve the name of the datasource from the instance. So I had to content myself with the catalog name:
connectionProvider.getConnection().getCatalog();