2016-03-31 58 views
1

我正在使用Liquibase變更集更新customId列的null值。 sql是this answer的修改版本。在Liquibase變更集中生成UUID時出現重複項異常

問題是它似乎對所有行使用相同的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> 

需要注意的是,如果我運行查詢的這個略微修改後的版本在MySQL控制檯(加2的限制),那麼它的工作原理:

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 

需要注意的是有合作的在customId上註冊UNIQUE約束 - 但不應該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識別。

相關問題