2016-03-31 6 views
1

Я использую набор изменений Liquibase для обновления null значений столбца customId. Sql - это модифицированная версия this answer.Повторяющаяся запись Исключение при генерации UUID в файле изменений Liquibase

Проблема в том, что, похоже, для всех строк используется один и тот же UUID. Моя ревизия выглядит следующим образом:

<changeSet id="v3.0.3" author="msp" runAlways="false"> 
    <preConditions onFail="MARK_RAN"> 
     <not> 
      <sqlCheck expectedResult="0">select count(*) from FOOBAR where customId is null</sqlCheck> 
     </not> 
    </preConditions> 

    <sql>update FOOBAR set customId = concat('cu:', (select uuid())) where customId is null</sql> 
</changeSet> 

Обратите внимание, что, если я бегу это немного измененную версию запроса (добавление предел 2) в консоли MySQL, то он работает:

update FOOBAR set customId = concat('cu:', (select uuid())) where customId is null limit 2

Но если я пытаюсь запустить тот же запрос (включая ограничения) с LiquiBase, я получаю следующее исключение:

Caused by: liquibase.exception.MigrationFailedException: Migration failed for change set changelog/db.changelog-v3.0.3.xml::v3.0.3::msp: 
    Reason: liquibase.exception.DatabaseException: Error executing SQL update FOOBAR set customId = concat('cu:', (select uuid())) where customId is null limit 2: Duplicate entry 'cu:cde325da-f71f-11e5-95f8-d15a50829a7d' for key 'customId' 
    at liquibase.changelog.ChangeSet.execute(ChangeSet.java:554) 
    at liquibase.changelog.visitor.UpdateVisitor.visit(UpdateVisitor.java:43) 
    at liquibase.changelog.ChangeLogIterator.run(ChangeLogIterator.java:70) 
    at liquibase.Liquibase.update(Liquibase.java:195) 
    at liquibase.Liquibase.update(Liquibase.java:174) 
    at liquibase.integration.spring.SpringLiquibase.performUpdate(SpringLiquibase.java:330) 
    at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:287) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1625) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1562) 
    ... 77 more 
Caused by: liquibase.exception.DatabaseException: Error executing SQL update FOOBAR set customId = concat('cu:', (select uuid())) where customId is null limit 2: Duplicate entry 'cu:cde325da-f71f-11e5-95f8-d15a50829a7d' for key 'customId' 
    at liquibase.executor.jvm.JdbcExecutor.execute(JdbcExecutor.java:62) 
    at liquibase.executor.jvm.JdbcExecutor.execute(JdbcExecutor.java:122) 
    at liquibase.database.AbstractJdbcDatabase.execute(AbstractJdbcDatabase.java:1206) 
    at liquibase.database.AbstractJdbcDatabase.executeStatements(AbstractJdbcDatabase.java:1189) 
    at liquibase.changelog.ChangeSet.execute(ChangeSet.java:518) 
    ... 85 more 
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'cu:cde325da-f71f-11e5-95f8-d15a50829a7d' for key 'customId' 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526) 
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411) 
    at com.mysql.jdbc.Util.getInstance(Util.java:386) 
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1039) 
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4096) 
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4028) 
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2490) 
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2651) 
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2677) 
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2627) 
    at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:841) 
    at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:681) 
    at com.mchange.v2.c3p0.impl.NewProxyStatement.execute(NewProxyStatement.java:1006) 
    at liquibase.executor.jvm.JdbcExecutor$ExecuteStatementCallback.doInStatement(JdbcExecutor.java:310) 
    at liquibase.executor.jvm.JdbcExecutor.execute(JdbcExecutor.java:55) 
    ... 89 more 

Заметьте, что есть о сотрудничестве urse a UNIQUE ограничение на customId - но не должно select uuid() (также попробовал uuid() без выбора) генерирует уникальное значение даже при использовании Liquibase?

ответ

1

Проблема может быть решена с помощью небольшого обходного пути. Я разделил обновление на два запроса:

<changeSet id="v3.0.3" author="msp" runAlways="false"> 
    <preConditions onFail="MARK_RAN"> 
     <not> 
      <sqlCheck expectedResult="0">select count(*) from FOOBAR where customId is null</sqlCheck> 
     </not> 
    </preConditions> 

    <sql>update FOOBAR set customId = (select uuid())) where customId is null</sql> 
    <sql>update FOOBAR set customId = concat('cu:', customId) where length(customId) = 36 
</changeSet> 

Это, конечно, работает только для моего случая, когда я могу быть уверен, что все строки первого запроса могут быть идентифицированы length(customId) = 36.