# HG changeset patch # User Oleksandr Gavenko # Date 1450816140 -7200 # Node ID da2130eaa11560c4a64353722b0d0a3f64255fe8 # Parent 248ed4d46099fa66770799f0f5137ce5b1f6bb08 How changelogs are identified. diff -r 248ed4d46099 -r da2130eaa115 liquibase.rst --- a/liquibase.rst Mon Dec 21 18:18:56 2015 +0200 +++ b/liquibase.rst Tue Dec 22 22:29:00 2015 +0200 @@ -20,9 +20,9 @@ * works only with current changes becase Liquibase basically work only with changesets and only special supplied instruments care about full schema definition -To create full schema debinition you may run:: +To create full schema definition in LiquiBase XML changelog format you may run:: - mvn liquibase:generateChangeLog -Dliquibase.outputChangeLogFile=... + $ mvn liquibase:generateChangeLog -Dliquibase.outputChangeLogFile=... on clean project without Liquibase. Or set name for changelog output file in ``pom.xml``. (here reduced not fully worked declaration):: @@ -52,3 +52,280 @@ +To create full schema definition in LiquiBase SQL format you may first to dump +your schema definition:: + + $ mysqldump --no-data -u $USER -p $DB_NAME > schema.sql + +then check ``schema.sql`` for danger operations. For example I forget to add +``--skip-add-drop-table`` option to ``mysqldump`` and so remove any ``DROP +TABLE`` lines by editor. + +Becase we already have tables I replace ``CREATE TABLE`` statements with:: + + CREATE TABLE IF NOT EXISTS + +Now my file is safely can be applied to production database without loosing +data and can recreate new schema in empty database. + +Generate difference between databases. +====================================== + +`This site +`_ +suggest using Hibernate ``hibernate.hbm2ddl.auto=create`` to create clean schema +with Hibernate and compare it with previous one. So you: + + * create empty schema and grand permissions for user + * register project to new user and schema, for example with Spring config:: + + + + + + + + + + + + + + + + + + + + org.hibernate.dialect.MySQLDialect + create + schema_v2_0 + + + + + * run Hibernate initialisation code via test or application deploy so + ``hibernate.hbm2ddl.auto=create`` trigger to new schema generation. + + * configure Maven ``pom.xml`` with paths and authentication data to old and new + schema:: + + + org.liquibase + liquibase-maven-plugin + ${liquibase.version} + + ${basedir}/src/main/resources/sql/master.xml + changelogDiff.xml + false + + com.mysql.jdbc.Driver + dbuser + 123456 + jdbc:mysql://localhost:3306/app + schema_v1.1 + + com.mysql.jdbc.Driver + dbuser + 123456 + jdbc:mysql://127.0.0.1:3306/app + schema_v2.0 + + + + mysql + mysql-connector-java + 5.1.6 + + + + + .. NOTE:: + + ``username`` and ``referenceUsername`` as ``url`` and ``referenceUrl``, + and ``defaultSchemaName`` and ``referenceDefaultSchemaName``, etc pairs + should be adopted to your connection/authentication data. This settings + also possible externalize to:: + + ${basedir}/src/main/resources/sql/master.xml + + * Review diff in ``changelogDiff.xml`` after:: + + $ mvn liquibase:diff + +Resulted ``changelogDiff.xml`` may be registered to project with ``schema_v1.1`` +schema state. + +It is possible to move inner part of ``changelogDiff.xml`` to the last changeset +that managed by LiquiBase in your project. + +Alternatively that file may be registered via ```` syntax. + +After that staying in project at ``schema_v1.1`` state you may upgrade from +``schema_v1.1`` to ``schema_v2.0`` schema by:: + + $ mvn liquibase:update + +Or create, review and apply SQL upgrade script (for your DBA):: + + $ mvn liquibase:updateSQL + +TODO: + + $ mvn liquibase:update -Dliquibase.changesToApply=1 + +Generating difference between database and JPA. +=============================================== + +LiquiBase come with plug-in which mimics like SQL driver. So we may run:: + + $ mvn liquibase:diff + +to get difference in LiquiBase XML format between our current database and JPA +schema description. + +With:: + + $ mvn liquibase:updateSQL + +we get SQL update code to state that described by Hibernate. + +Depending on Hibernate metadata form we shoud adapt ``referenceUrl`` property. +For example for Spring enabled project with JPA annotations:: + + hibernate:spring:com.app.domain?dialect=org.hibernate.dialect.MySQLDialect + +Here ``com.app.domain`` represent package with JPA annotated entities. + +So complete reference visit: +https://github.com/liquibase/liquibase-hibernate/wiki + +Also we need Spring Beans and LiquiBase driver in classpath to resolve +dependencies during diff calculation. Complete Maven piece look like:: + + + org.liquibase + liquibase-maven-plugin + ${liquibase.version} + + ${basedir}/src/main/resources/sql/master.xml + ${liquibase.profile} + false + info + com.mysql.jdbc.Driver + app + app + + + migration.sql + + hibernate:spring:com.app.domain?dialect=org.hibernate.dialect.MySQLDialect + changelogDiff.xml + tables,views,columns,indexes,foreignkeys,primarykeys,uniqueconstraints + + + + org.springframework.data + spring-data-jpa + ${spring-data.version} + + + org.liquibase.ext + liquibase-hibernate4.2 + 3.5 + + + + +http://stackoverflow.com/questions/27877154/liquibase-and-jpa-annotated-entities + +http://www.baeldung.com/liquibase-refactor-schema-of-java-app + +How changelogs are identified. +============================== + +Upstream deside use three field to identify changeset: + + * each changeset mandatory marked by pair of ``user:id`` (which is actually any + non-whitespace characters) + * full path to file with changeset + +``user:id`` is actually any non-whitespace and non-colon text with +non-whitespace text. Upstream suggest to use changeset authro identity for +``user`` and numbers or reason/name for changeset for ``id``. + +``user:id`` pair should be unique for file. + +Reason to capture full path as part of identifier is very dumb. Upstream +arguments: + + * http://forum.liquibase.org/topic/why-does-the-change-log-contain-the-file-name + * http://forum.liquibase.org/topic/i-need-to-ignore-the-filename-in-the-processing-to-see-if-a-change-set-has-already-been-applied + * http://forum.liquibase.org/topic/logical-filepath-in-change-sets-and-changelog + +is very Java centric and require sticking to fixed changeset file location in +``CLASSPATH``. + +When you work with same file on different hosts / tools you should very +carefully check that path satisfy conventions that used with previous LiquiBase +work for concrete DB. + +I have incompatibilities between String integration and Maven plug-in. Because I +use full path in Maven and CLASSPATH relative in String. + +Hopefully there is logicalFilePath attribute. + +In XML syntax in may be applied to top level tag:: + + + ... + + +or may be overridden by each changeset:: + + + ... + + +SQL syntax also have ``logicalFilePath`` attribute for top level file mark +(implemented in v3.3): + + --liquibase formatted sql logicalFilePath:legacy.sql + +and may be overridden by each changeset:: + + --changeset legacy:1 logicalFilePath:other.sql + +To verify that settings have effect run:: + + mvn liquibase:changelogSyncSQL + +and review migration.sql. Corresponding ``pom.xml`` part:: + + + org.liquibase + liquibase-maven-plugin + ${liquibase.version} + + ${basedir}/src/main/resources/sql/master.xml + ${liquibase.profile} + false + + migration.sql + + + +.. + + * http://stackoverflow.com/questions/19896436/how-to-configure-liquibase-not-to-include-file-path-or-name-for-calculating-chec + * http://stackoverflow.com/questions/19959755/liquibase-how-to-disable-filename-column-check + * http://stackoverflow.com/questions/18767815/refactoring-liquibase-changelog-files + +Consult +``liquibase-core/src/main/java/liquibase/parser/core/formattedsql/FormattedSqlChangeLogParser.java`` +for further info . +