我有几个应该使用 HSQLDB 的单元测试,但我知道其中一些实际上是在访问物理数据库。我想在测试中添加一个检查,以确保正在使用的 DataSource 用于 HSQLDB 而不是 live DB。
从休眠会话对象(org.hibernate.classic.Session
),我如何检查数据源
更新:
我还可以访问会话工厂 ( org.hibernate.impl.SessionFactory
)。
详细信息:休眠 3.2
不管 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,检查驱动程序名称,检查几乎所有内容)。
编辑:上面的方法适用于休眠 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");
}
如果它是 的子类AbstractTransactionalDataSourceSpringContextTests
,那么您尝试过
getJdbcTemplate().getDataSource()
吗?
否则你可以试试
((SessionImplementor) session).getJdbcConnectionAccess().obtainConnection()
.getMetaData().getDatabaseProductName()
但这有点恶心。:) 并且似乎在 Hibernate 4.x 中引入。
在旧版本上使用现已弃用的:
((SessionImpl) session).getSessionFactory().getConnectionProvider()
.getConnection().getMetaData().getDatabaseProductName();
这完全是一个技巧,可能不起作用,因为您需要转换为您的设置可能未使用的特定类。
SessionFactoryImpl factory = (SessionFactoryImpl) session.getSessionFactory(); // or directly cast the sessionFactory
DatasourceConnectionProviderImpl provider = (DatasourceConnectionProviderImpl)factory.getConnectionProvider();
DataSource dataSource = provider.getDataSource();
factory.getConnectionProvider()
返回ConnectionProvider
可以由任意数量的类实现的(接口)实例。其中之一是DatasourceConnectionProviderImpl
,然后您可以使用它来获取数据源。
DatasourceConnectionProviderImpl
应该是默认值,除非您使用的是休眠 C3P0 或 Proxool 池。
如果您想在不打开新连接的情况下检测数据库提供者,您可能会发现使用方言类很有用。
String dialectName = ((SessionFactoryImplementor)sessionFactory).getDialect().getClass().getSimpleName().toLowerCase();
if(dialectName.contains("oracle"))
...
else if(dialectName.contains("mysql"))
...