可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
...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 particular EntityManager
.
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();
回答1:
You need to:
- cast the
EntityManager
to EntityManagerImpl
(the Hibernate implementation)
- call
getFactory()
- cast the
EntityManagerFactory
to HibernateEntityManagerFactory
- call
getSessionFactory()
and cast it to SessionFactoryImpl
- call
getConnectionProvider()
and cast it to the correct implementation. You can see the implementations here. I'll assume that it's a DatasourceConnectionProvider
- 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.
回答2:
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.
回答3:
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();
}
回答4:
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");
回答5:
Try this :
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();
回答6:
I'm using Hibernate 5.0.x
This is how I'm getting a connection from the persistence pool:
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();
}
The emf
parameter is JPA's standard javax.persistence.EntityManagerFactory
, typically acquired globally using:
emf = Persistence.createEntityManagerFactory("persistence-unit-name");
or by injection:
@PersistenceUnit(unitName="persistence-unit-name")
EntityManagerFactory emf;
回答7:
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).
回答8:
Here's what helped me. I use HikariCP but I don't think it matters.
Basically what needs to be done is
- find a service registry
- get service by
org.hibernate.engine.jdbc.connections.spi.ConnectionProvider
class
- unwrap it to
javax.sql.DataSource
.
Service registry can be retrieved from EntityManager
((SessionImpl) em).getFactory().getServiceRegistry()
or from EntityManagerFactory directly
((SessionFactoryImpl) entityManagerFactory).getServiceRegistry()