problem integrating Liquibase Spring bean

Hello,
I have been playing with liquibase maven plugin and it works great.
I have defined a db.changelog.xml with 2 changesets.
I am able to run maven plugin to recreate database by running changeset 1, for instance.

Now, I am trying to achieve the autoupdate of database when deploying my web-app.

For this, I have added the spring bean:

  1.    
  2.        
  3.        
  4.        
  5.    

When I run my web-app, liquibase tries to run changeset 1, even though it is registered in databasechangelog table. I was expecting the spring bean would automatically skip changeset 1 and run only changeset 2, but I get a migration exception. What am I missing?

  1. INFO 31/01/12 15:48:liquibase: Successfully acquired change log lock
  2. WARNING 31/01/12 15:48:liquibase: Current XML parsers seems to not support EntityResolver2. External entities won’t be correctly loaded
  3. INFO 31/01/12 15:48:liquibase: Reading from vetisigma.DATABASECHANGELOG
  4. INFO 31/01/12 15:48:liquibase: Reading from vetisigma.DATABASECHANGELOG
  5. SEVERE 31/01/12 15:48:liquibase: Change Set classpath:db/db.changelog.xml::1::jg (generated) failed.  Error: Error executing SQL CREATE TABLE mydb.admin_route (id BIGINT AUTO_INCREMENT NOT NULL, name VARCHAR(50) NOT NULL, CONSTRAINT PK_ADMIN_ROU</li><li>TE PRIMARY KEY (id)): Table ‘admin_route’ already exists
  6. liquibase.exception.DatabaseException: Error executing SQL CREATE TABLE mydb.admin_route (id BIGINT AUTO_INCREMENT NOT NULL, name VARCHAR(50) NOT NULL, CONSTRAINT PK_ADMIN_ROUTE PRIMARY KEY (id)): Table ‘admin_route’ already exists
  7.         at liquibase.executor.jvm.JdbcExecutor.execute(JdbcExecutor.java:62)
  8.         at liquibase.executor.jvm.JdbcExecutor.execute(JdbcExecutor.java:104)

My changeset file:
  1.    
  2.        
  3.            
  4.                
  5.            
  6.            
  7.                
  8.            
  9.        
  10.    
  11.    
  12.    

Ok. Got it, by debugging ChangeLogIterator.
I have seen that the class ShouldRunChangeSetFilter, in order to decide if it should run a changeSet, takes into account:

  •  id
  • author
  • path
so all these three values in the databasechangelog table should match those in the xml changelog.
The thing is, if you run one changeset via maven plugin, the file path will be something like target/classes/db/db.changelog.xml, while if you run the same changeset via spring bean, the path will be different: classpath:db/db.changelog.xml. This provokes that the ShouldRunChangeSetFilter sees the same changeset as two different ones and the changeset is run, thus provoking the exception.


Another argument for using the changeSet element.


http://about.me/lairdnelson

Ok. This was not so obvious in the documentation. Thanks!

Is it possible to have liquibase log all database changes performed via spring bean?

Thanks for your reply.

Ok.
In fact we are using the spring bean to make sure the app has the correct database version on startup. A log of performed ops would be a plus for productions environments. It would be more… confident?

Cheers,
Josep

Not as it exists, but you can look at the source for the spring bean to see how to call liquibase, and use the Liquibase.update() method that generates SQL vs. executing the SQL.


The expectation with the spring bean is that it is used in cases where you want to to make sure the database is up to date on startup. Generating SQL is usually a different process, so it is not included in the normal codebase currently.

Nathan

I could see that. There is a way to run liquibase under debug log level which should output what is executed as well, although there is no setup in the existing spring listener to support setting that.


Nathan