问题 如何从实体管理器获取数据库元数据


我有一个使用hibernate和jpa的应用程序。我需要找出它连接到哪个数据库,以便我基于db执行的一些本机sql查询例如。 oracle和postgres。如果我使用的是纯jdbc,那么直接获取db元数据但不知道如何从实体管理器获取

谢谢


5717
2018-05-15 19:05


起源



答案:


作为一种解决方法,您可以获取 EntityManagerFactory 用于获取底层数据库配置的属性,这是特定于实现的。

  • 过冬 : hibernate.connection.driver_class

  • EclipseLink:  eclipselink.target-database 此属性指定目标数据库。在你的情况下,它可能有价值 Oracle 要么 PostgreSQL 各个数据库。

  • 一般 :  javax.persistence.jdbc.driver 

根据此信息,您可以获取当前连接的数据库。

EntityManagerFactory emf = entityManager.getEntityManagerFactory();     
Map<String, Object> emfProperties = emf.getProperties();

String driverClass = (String)emfProperties.get(PROPERTY);
//-- For PostgreSQL, it will have value "org.postgresql.Driver"

if(driverClass.lastIndexOf("postgresql") != -1)
    postGreSQL_DB = true;

注意 :  您的应用程序设计不太清楚,但可能会发生您的应用程序连接到两个数据库。如果可能,您可以尝试分开 EntityManager 对于每个数据库,指向不同的持久性单元 persistence.xml 并可以相应地使用它。

如果不是这种情况,并且一次只连接其中一个,那么您可以简单地验证它 entityManager.isOpen() 要么 emf.isOpen()

编辑: 

Connection connection = entityManager.unwrap(Connection.class);  
DatabaseMetaData metaData = connection.getMetaData();

现在,您可以从中获取数据库产品名称,驱动程序等。


5
2018-05-15 20:56



感谢Nayan提供这些有用的提示。当我试图从em获取emf时,我没有看到它们所以我想出了这个代码DatabaseMetaData dbmd =((Session)entityManager.getDelegate())。connection()。getMetaData(); dbName = dbmd.getDatabaseProductName(); - user509755
我不知道这个代码是可移植到diff服务器和正确的做法,因为hibernate将从版本4.x中删除connection()方法。但是现在这对我有用。 - user509755
@ user509755很高兴你发现它很有帮助。我已经尝试过实体经理,因为你已经提到了它。此外,当您尝试使用实体管理器时发生了什么。您可以将其作为答案发布,也可以帮助某人。 - Nayan Wadekar
我没有在我的entitymanager上看到名为getEntityManagerFactory()的方法。这就是我必须找到替代选项的原因,正如我之前提到的那样。 - user509755
@ user509755它在Java EE 6中,可以参考 docs.oracle.com/javaee/6/api/javax/persistence/... - Nayan Wadekar


答案:


作为一种解决方法,您可以获取 EntityManagerFactory 用于获取底层数据库配置的属性,这是特定于实现的。

  • 过冬 : hibernate.connection.driver_class

  • EclipseLink:  eclipselink.target-database 此属性指定目标数据库。在你的情况下,它可能有价值 Oracle 要么 PostgreSQL 各个数据库。

  • 一般 :  javax.persistence.jdbc.driver 

根据此信息,您可以获取当前连接的数据库。

EntityManagerFactory emf = entityManager.getEntityManagerFactory();     
Map<String, Object> emfProperties = emf.getProperties();

String driverClass = (String)emfProperties.get(PROPERTY);
//-- For PostgreSQL, it will have value "org.postgresql.Driver"

if(driverClass.lastIndexOf("postgresql") != -1)
    postGreSQL_DB = true;

注意 :  您的应用程序设计不太清楚,但可能会发生您的应用程序连接到两个数据库。如果可能,您可以尝试分开 EntityManager 对于每个数据库,指向不同的持久性单元 persistence.xml 并可以相应地使用它。

如果不是这种情况,并且一次只连接其中一个,那么您可以简单地验证它 entityManager.isOpen() 要么 emf.isOpen()

编辑: 

Connection connection = entityManager.unwrap(Connection.class);  
DatabaseMetaData metaData = connection.getMetaData();

现在,您可以从中获取数据库产品名称,驱动程序等。


5
2018-05-15 20:56



感谢Nayan提供这些有用的提示。当我试图从em获取emf时,我没有看到它们所以我想出了这个代码DatabaseMetaData dbmd =((Session)entityManager.getDelegate())。connection()。getMetaData(); dbName = dbmd.getDatabaseProductName(); - user509755
我不知道这个代码是可移植到diff服务器和正确的做法,因为hibernate将从版本4.x中删除connection()方法。但是现在这对我有用。 - user509755
@ user509755很高兴你发现它很有帮助。我已经尝试过实体经理,因为你已经提到了它。此外,当您尝试使用实体管理器时发生了什么。您可以将其作为答案发布,也可以帮助某人。 - Nayan Wadekar
我没有在我的entitymanager上看到名为getEntityManagerFactory()的方法。这就是我必须找到替代选项的原因,正如我之前提到的那样。 - user509755
@ user509755它在Java EE 6中,可以参考 docs.oracle.com/javaee/6/api/javax/persistence/... - Nayan Wadekar


在Hibernate 4中,您可以使用该代码从实体管理器获取数据库信息:

org.hibernate.engine.spi.SessionImplementor sessionImp = 
     (org.hibernate.engine.spi.SessionImplementor) eManager.getDelegate();
DatabaseMetaData metadata = sessionImp.connection().getMetaData();
//do whatever you need with the metadata object...
metadata.getDatabaseProductName();

干杯

灵光


5
2017-10-03 02:01



在较新的版本中,pff Hibernate 3也可以。 - SkorpEN
我如何获得实体经理(eManager)? - sakra


基于Emmanuel回答如何使用Spring和hibernate:

 @Repository
 public class UserRepository {

    @PersistenceContext
    private EntityManager em;

    public void getMeta() {
        org.hibernate.engine.spi.SessionImplementor sessionImp = (org.hibernate.engine.spi.SessionImplementor) em.getDelegate();
        DatabaseMetaData metadata = null;
        try {
            metadata = sessionImp.connection().getMetaData();
            ResultSet res = metadata.getColumns(null, null, "USERS", "USERNAME");
            System.out.println("List of columns: ");
            while (res.next()) {
                System.out.println(
                        "  " + res.getString("TABLE_SCHEM")
                                + ", " + res.getString("TABLE_NAME")
                                + ", " + res.getString("COLUMN_NAME")
                                + ", " + res.getString("TYPE_NAME")
                                + ", " + res.getInt("COLUMN_SIZE")
                                + ", " + res.getInt("NULLABLE"));
            }
            res.close();
            System.out.println();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

2
2018-03-04 00:07





如果其他人(像我一样)想要尝试获取一些jdbc信息而你正在使用hibernate 4.x,你可以尝试这样:

import java.sql.Connection;
import java.sql.SQLException;
import org.hibernate.jdbc.Work;
public class ConnectionInfo implements Work {

public String dataBaseUrl;
public String dataBaseProductName;
public String driverName;

@Override
public void execute(Connection connection) throws SQLException {
    dataBaseUrl = connection.getMetaData().getURL();
    dataBaseProductName = connection.getMetaData().getDatabaseProductName();
    driverName = connection.getMetaData().getDriverName();
}

public String getDataBaseProductName() {
    return dataBaseProductName;
}

public void setDataBaseProductName(String dataBaseProductName) {
    this.dataBaseProductName = dataBaseProductName;
}

public String getDataBaseUrl() {
    return dataBaseUrl;
}

public void setDataBaseUrl(String dataBaseUrl) {
    this.dataBaseUrl = dataBaseUrl;
}

public String getDriverName() {
    return driverName;
}

public void setDriverName(String driverName) {
    this.driverName = driverName;
}
}

现在您可以检索您的信息:

// -- snip
org.hibernate.ejb.EntityManagerImpl entityManagerImpl =  (org.hibernate.ejb.EntityManagerImpl) genericDBAccess.getEntityManager().getDelegate();
    Session session = entityManagerImpl.getSession();
    connectionInfo = new ConnectionInfo();
    session.doWork(connectionInfo);
// -- snap

希望有所帮助!我疯狂地发现这些信息....


0
2018-05-29 09:46