I have several unit tests that should be using a HSQLDB but I know some of them are actually hitting a physical DB. I want to add a check to the test to make sure that the DataSource being used is for HSQLDB and not the live DB.
From a hibernate session object (org.hibernate.classic.Session
), How do I check the DataSource
Update:
I also have access to the session factory (org.hibernate.impl.SessionFactory
).
Details: Hibernate 3.2
hibernate. connection. datasource property is used to provide the DataSource name that will be used by Hibernate for database operations.
Hibernate SessionFactory openSession() method always opens a new session. We should close this session object once we are done with all the database operations. We should open a new session for each request in multi-threaded environment.
In hibernate framework, we have Transaction interface that defines the unit of work. It maintains abstraction from the transaction implementation (JTA,JDBC). A transaction is associated with Session and instantiated by calling session. beginTransaction().
The Hibernate transaction API delegates the begin/commit/rollback to the JDBC Connection for local transactions and to the associated UserTransaction for JTA. Therefore, you can run multiple transactions on the same Hibernate Session, but there's a catch.
Regardless of wrappers and concrete implementation of Hibernate/Spring and so on, you may check not DataSource, but database type (and this might be suitable).
The idea is in the usage of DatabaseMetaData and check type against it (as Hibernate detects dialect):
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");
}
});
}
Note, that body of method can be changed in the way you want (check JDBC URL, check driver name, check almost anything).
Edit: approach above is working for hibernate 3.5+.
For Hibernate earlier version(e.g. 3.2) it might be even easier:
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");
}
If it's a subclass of AbstractTransactionalDataSourceSpringContextTests
, then have you tried
getJdbcTemplate().getDataSource()
?
Otherwise you could try
((SessionImplementor) session).getJdbcConnectionAccess().obtainConnection()
.getMetaData().getDatabaseProductName()
But it that's kind of disgusting. :) And seems to get introduced in Hibernate 4.x.
On older versions use the now deprecated:
((SessionImpl) session).getSessionFactory().getConnectionProvider()
.getConnection().getMetaData().getDatabaseProductName();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With