For a project of mine, I want to use Liquibase to generate database modifications in real time. Hibernate’s DDL capabilities just don’t cut the mustard.
But I have not found anywhere about how to do. Here is the code I came up with so far:
final HashMap<String, String> settings = new HashMap<String, String>();
Well, this doesn’t work. The last line throws NPE.
I am at a loss. The thing is, I do NOT want to use an XML file to generate the changes. As I want to generate changes in real time, I’ll spawn Change objects in order to… Well, what? How do I operate from there?
OK, well, I have had some sort of success. I’ve had to create an XML file with the described changeset and the org.liquibase.Liquibase objet did the trick.
But I really wish it were easier to generate a DDL change set without having to go through an XML file… Anyway, here is the code that I came up with:
public class LiquiBaseDemo { public static void main(final String… args) throws LiquibaseException { final ClassLoader myself = LiquiBaseDemo.class.getClassLoader(); final ResourceAccessor ra = new ClassLoaderResourceAccessor(myself); final HashMap<String, String> settings = new HashMap<String, String>();
settings.put(“hibernate.connection.driver_class”, “org.hsqldb.jdbcDriver”); settings.put(“hibernate.connection.url”, “jdbc:hsqldb:mem:testdb”); settings.put(“hibernate.connection.username”, “sa”); settings.put(“hibernate.connection.password”, “”); settings.put(“hibernate.dialect”, “org.hibernate.dialect.HSQLDialect”); settings.put(“hibernate.show_sql”, “true”); final Properties props = new Properties(); props.putAll(settings);
final Configuration cfg = new Configuration(); cfg.addProperties(props);
final SessionFactory sf = cfg.buildSessionFactory(); final Session s = sf.openSession(); final Connection c = s.connection();
No, not in detail. It doesn’t really do what I want from what I’ve seen so far. I do mean real time: generating changelogs, mappings etc on the fly. And I want to use Liquibase for DDL. Hibernate comes “after the fact” in my case.
While I could get Liquibase to work by generating a ChangeLog XML file, I really wish it were easier to generate a ChangeLog object (or is that another one) without generating an XML file.
The workflow I had considered for the hibernate/liquibase integration is to look at the hibernate mapping and database and build an XML file so that the the XML file can be inspected to ensure that the generated changes are actually what is expected. For example, it is easy for a column rename to be interpreted as a column drop and column add but you don’t want to actually do that or you will lose data.
OK well, it’s just a case of extending/implementing each and every object until I can at last pass at least a Dom4J document as the root of the changelog (yes, I also happen to hate Sun’s XML APIs…).
That’s not my plan. I separate the DDL operations in two: the ones which can be executed without affecting current DML sessions (creating tables, adding columns etc) and the ones which do affect current DML sessions (removing tables, adding constraints, dropping columns etc). I plan to handle these using specially crafted sessions which are schema-aware (I plan not to use POJOs at all for DML - they are not suited for the task).
Liquibase is the best solution I found for DDL, I just wish it were easier to use without filesystem backings
The normal usage of liquibase is to have physical files, but I would think you should be able to use the DatabaseChangeLog object without one. With 2.0, I attempted to refactor the codebase so you have various changelog parsers who convert from the physical file to the in-memory DatabaseChangeLog object. From that point, there all logic is taken from the changelog object, not from the original file. In your case, you should be able to build up the DatabaseChangeLog object yourself without using ChangeLogSAXHandler at all or any files at all.
You will need to assign a logical file name to your databasechangelog object, but that can be completely arbitrary and not map to an actual file.
ResourceAccessor would only be applicable if you did an sqlFile call, but you would only be doing that if you are creating physical sql files.