如何确定Hibernate会话正在使用的DataSource?

时间:2013-03-15 20:28:29

标签: java hibernate junit hsqldb

我有几个应该使用HSQLDB的单元测试,但我知道其中一些实际上正在使用物理数据库。我想在测试中添加一个检查,以确保所使用的DataSource用于HSQLDB,而不是实时DB。

从hibernate会话对象(org.hibernate.classic.Session),如何检查DataSource

更新 我也可以访问会话工厂(org.hibernate.impl.SessionFactory)。

详细信息: Hibernate 3.2

4 个答案:

答案 0 :(得分:7)

无论Hibernate / Spring等的包装器和具体实现如何,您可以检查不是DataSource,而是检查数据库类型(这可能是合适的)。

这个想法是使用DatabaseMetaData并检查它的类型(因为Hibernate检测到方言):

private boolean isTestDb(Session session) {
    return session.doReturningWork(new ReturningWork<Boolean>() {
        @Override
        public Boolean execute(Connection connection) throws SQLException {
            DatabaseMetaData metaData = connection.getMetaData();
            return metaData.getDatabaseProductName().startsWith("HSQL");
        }
    });
}

注意,可以按照您想要的方式更改方法体(检查JDBC URL,检查驱动程序名称,检查几乎所有内容)。

编辑:上面的方法适用于hibernate 3.5 +。

对于Hibernate早期版本(例如3.2),它可能更容易:

private boolean isTestDb(Session session) {
    Conection connection = session.connection();//deprecated method, which was dumped in hibernate 3.5+
    DatabaseMetaData metaData = connection.getMetaData();
    return metaData.getDatabaseProductName().startsWith("HSQL");
}

答案 1 :(得分:2)

如果它是AbstractTransactionalDataSourceSpringContextTests的子类,那么你试过吗? getJdbcTemplate().getDataSource()

否则你可以尝试

((SessionImplementor) session).getJdbcConnectionAccess().obtainConnection()
       .getMetaData().getDatabaseProductName()

但这有点令人作呕。 :)似乎在Hibernate 4.x中引入了。

编辑:

在旧版本中使用现已弃用的:

    ((SessionImpl) session).getSessionFactory().getConnectionProvider()
                           .getConnection().getMetaData().getDatabaseProductName();

答案 2 :(得分:1)

这是完全黑客攻击,可能无法正常工作,因为您需要转换为您的设置可能未使用的特定类。

SessionFactoryImpl factory = (SessionFactoryImpl) session.getSessionFactory(); // or directly cast the sessionFactory
DatasourceConnectionProviderImpl provider = (DatasourceConnectionProviderImpl)factory.getConnectionProvider();
DataSource dataSource = provider.getDataSource();

factory.getConnectionProvider()返回可以实现by any number of classesConnectionProvider(接口)实例。其中一个是DatasourceConnectionProviderImpl,您可以使用它来获取数据源。

DatasourceConnectionProviderImpl应该是默认值,除非您使用的是休眠C3P0或Proxool池。

答案 3 :(得分:0)

如果要在不打开新连接的情况下检测数据库提供程序,您可能会发现使用方言类很有用。

    String dialectName = ((SessionFactoryImplementor)sessionFactory).getDialect().getClass().getSimpleName().toLowerCase();
    if(dialectName.contains("oracle"))
        ...
    else if(dialectName.contains("mysql"))
        ...