Hi there,
I’m currently trying to incorporate Liquibase in our project. We use JPA / Hibernate and our domain model is rather complicated. We had to create some initial data in our database, and instead of doing it using SQL I thought of doing it using a CustomTaskChange.
The first problem was that the EntityManagerFactory likes to have a connection specified in a configuration file, but I didn’t want to have that information duplicated, so I solved it using an Hibernate ConnectionProvider built inside CustomTaskChange.execute:
-
public class LiquibaseConnectionProvider implements ConnectionProvider {
public static final String LIQUIBASE_CONNECTION = "xxxx.commons.db.liquibase_database";
protected Database database;
@Override
public void close() throws HibernateException {
}
@Override
public void closeConnection(Connection connection) throws SQLException {
}
@Override
public void configure(Properties properties) throws HibernateException {
this.database = (Database) properties.get(LiquibaseConnectionProvider.LIQUIBASE_CONNECTION);
}
@Override
public Connection getConnection() throws SQLException {
return this.database.getConnection().getUnderlyingConnection();
}
@Override
public boolean supportsAggressiveRelease() {
return false;
}
}
public class DataCreation implements CustomTaskChange
{
@Override
public void execute( Database database ) throws CustomChangeException, UnsupportedChangeException
{
Map<String, Object> properties = new HashMap<String, Object>( );
properties.put( Environment.DIALECT, “whatever.your.dialect” );
properties.put( Environment.CONNECTION_PROVIDER, “com.example.package.LiquibaseConnectionProvider” );
properties.put( LiquibaseConnectionProvider.LIQUIBASE_CONNECTION, database );
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory( “gloxr”, properties );
EntityManager entityManager = entityManagerFactory.createEntityManager( );
… // I guess you get the point
}
This way I’m able to create an entity manager that uses the database connection provided by Liquibase. The problem with this approach is that I have to create the EntityManagerFactory every time a CustomTaskChange is called. This is a costly operation (specially when you have a rich domain model), and it only makes sense to do it once during a Liquibase database update.
I was thinking on creating some kind of singleton that would initialize the EntityManagerFactory on first call, and then would return that factory to any subsequent call, but first of all, I wasn’t sure Liquibase would always use the same connection to do all the operations on the database, and then I thought that what I’d really like is Liquibase to provide this kind of integration: I mean, if used with Hibernate or JPA, Liquibase could initialize the EntityManagerFactory, and pass the EntityManager as a parameter to the execute method on CustomTaskChange (or JPACustomTaskChange).
What do you think? Is there any workaround using the current API, maybe what I mentioned about using a singleton and assuming the Database object will always be the same?
Best regards
Jos�