如何以编程方式检索持久性单元使用的数据源

时间:2012-09-14 11:48:26

标签: hibernate java-ee jpa jpa-2.0 jboss7.x

...没有实际阅读和解析persistence.xml

我可以使用properties of it's factory检索EntityManager的持久性单元的名称。我可以使用jboss-as-controller-client检索可用的数据源。但我发现没有API可以为我提供特定EntityManager的数据源。

名称String即可。

谢谢

我在JBoss 7.1.1.Final上使用Hibernate 4.0.1.Final而不是JPA 2。

编辑:我想尽可能避免从JPA转向Hibernate API。

编辑:Augusto的解决方案有效,我对细节有一些注意事项:由于ClassCastException :( org.jboss.as.jpa.container.TransactionScopedEntityManager cannot be cast to org.hibernate.ejb.EntityManagerImpl),EM的投射不起作用,但它适用于检索到的工厂。所以我省略了第1步。

我也找不到从实例中检索数据源名称的方法。所以我不得不满足于目录名称:connectionProvider.getConnection().getCatalog();

10 个答案:

答案 0 :(得分:19)

你需要:

  1. EntityManager强制转换为EntityManagerImpl(Hibernate实现)
  2. 致电getFactory()
  3. EntityManagerFactory强制转换为HibernateEntityManagerFactory
  4. 致电getSessionFactory()并将其投放至SessionFactoryImpl
  5. 调用getConnectionProvider()并将其转换为正确的实现。您可以看到实现here。我会假设它是DatasourceConnectionProvider
  6. 致电getDataSource(),您就完成了。
  7. 不幸的是,您必须使用Hibernate API,因为无法使用JPA API检索DataSource。

答案 1 :(得分:8)

如果您只想要数据源的名称并且每个JPA意味着提供了该数据源名称,那么您应该能够通过以下方式获取该信息:

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

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

取决于您如何定义数据源。

答案 2 :(得分:7)

在Spring环境中,你可以使用它:

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

@PersistenceContext
EntityManager entityManager;

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

答案 3 :(得分:4)

我需要这样做才能运行Flyway迁移。我无法使用Augusto的方法检索DataSource,但我能够通过检索url,username& amp;来重新创建数据源。 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 :(得分:3)

试试这个:

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

答案 5 :(得分:2)

我正在使用Hibernate 5.0.x

这就是我从持久性池获取连接的方式:

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

emf参数是JPA的标准javax.persistence.EntityManagerFactory,通常使用以下方式全球获取:

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

或通过注射:

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

答案 6 :(得分:1)

我正在使用hibernate 5.2.10.Final,以下代码对我有用:

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

您需要的只是将entityManager.getEntityManagerFactory()传递给此方法(对于我来说,我有多个工厂。然后可以在需要时使用此方法来获取其中任何一个的数据源)。

答案 7 :(得分:1)

DataSource dataSource = (DataSource) 
em.getEntityManagerFactory().getProperties()
            .get(org.hibernate.cfg.AvailableSettings.JPA_JTA_DATASOURCE);

您可以使用休眠方式检索数据源。经过Hibernate 5.3测试

答案 8 :(得分:0)

这就是帮助我的原因。我使用HikariCP,但我认为这并不重要。

基本上需要做的是

  1. 找到服务注册表
  2. org.hibernate.engine.jdbc.connections.spi.ConnectionProvider类获得服务
  3. 将其解包到javax.sql.DataSource

可以从EntityManager中检索服务注册表

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

或直接从EntityManagerFactory

((SessionFactoryImpl) entityManagerFactory).getServiceRegistry()

答案 9 :(得分:0)

在SpringBoot环境中,您可以使用以下内容:

@PersistenceContext
EntityManager entityManager;

private HikariDataSource getDataSourceFromHibernateEntityManager() {
    EntityManagerFactoryInfo info = (EntityManagerFactoryInfo) entityManager.getEntityManagerFactory();
    return (HikariDataSource) info.getDataSource();
}

public String getDataSourceProperties() {
    HikariDataSource dataSource = getDataSourceFromHibernateEntityManager();
    return "DataSource properties:" +
            "URL: " + dataSource.getJdbcUrl() + "\n" +
            "Default Schema: " + dataSource.getPoolName() + "\n" +
            "Driver Class Name: " + dataSource.getDriverClassName() + "\n" +
            "Username: " + dataSource.getUsername() + "\n";
}