Реализация контрольных сумм в миграциях Java

Мои миграции Java в настоящее время не реализуют интерфейс MigrationChecksumProvider. Мне интересно, если они должны.

Я не понимаю, какую роль контрольные суммы играют в Flyway. Кто-нибудь объяснит мне, пожалуйста? Кроме того, если я реализую MigrationChecksumProvider, как должна вычисляться контрольная сумма для данной миграции?

Спасибо.

2 ответа

Решение

Контрольная сумма используется для (случайного) обнаружения изменений миграций, что лишает законной силы гарантию того, что схема может быть воссоздана точно.

Для миграций Java небо - это предел того, что вы можете сделать. Следовательно, это ваш призыв к тому, как вы хотите реализовать контрольные суммы для обнаружения изменений.

Я думаю, что большую часть времени вы хотите вычислить контрольную сумму на основе содержимого файла класса, о котором идет речь. Мы делаем это так...

import java.io.IOException;
import java.io.InputStream;
import java.util.zip.CRC32;

import org.flywaydb.core.api.migration.jdbc.JdbcMigration;
import org.flywaydb.core.internal.util.FileCopyUtils;
import org.flywaydb.core.internal.util.logging.Log;
import org.flywaydb.core.internal.util.logging.LogFactory;

/**
 * Utility class for checksum calculations.
 * 
 */
public final class Checksums {

    private static final Log LOG = LogFactory.getLog(Checksums.class);

    private Checksums() {
        super(); // singleton
    }

    /**
     * Calculates a checksum based on the given JdbcMigration. It builds the checksum from the byte content of the given
     * migration class file using the same {@link CRC32} method as used by
     * {@link org.flywaydb.core.internal.resolver.sql.SqlMigrationResolver}
     * 
     * @param migration
     * @return the checksum
     */
    public static final Integer checksum(JdbcMigration migration) {
        Integer checksum = null;

        Class<?> migrationClass = migration.getClass();
        String migrationClassFilePath = migrationClass.getName().replace(".", System.getProperty("file.separator")) + ".class";
        InputStream inputStream = null;

        try {
            inputStream = ClassLoader.getSystemResourceAsStream(migrationClassFilePath);
            byte[] classContent = FileCopyUtils.copyToByteArray(inputStream);
            final CRC32 crc32 = new CRC32();
            crc32.update(classContent);
            checksum = (int) crc32.getValue();
        } catch (IOException ioe) {
            LOG.error("Problem calculating checksum for class " + migrationClass.getName(), ioe);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException ioe) {
                    LOG.error("Problem closing input stream to " + migrationClassFilePath, ioe);
                }
            }
        }
        return checksum;
    }    
}

Затем вы можете создать базовый класс, который выглядит как

public abstract class JdbcMigrationWithChecksum implements JdbcMigration, MigrationChecksumProvider {

    @Override
    public Integer getChecksum() {
        return Checksums.checksum(this);
    }
}
Другие вопросы по тегам