Как изменить databasechangelog.filename для Spring Boot и Liquibase?

Ниже представлен полный код класса Exceptional. Он имеет довольно большой API, который является чистым расширением API Optional, поэтому он может быть заменой для него в любом существующем коде, кроме того, что он не является подтипом конечного класса Optional. Класс можно рассматривать как находящийся в том же соотношении с монадой Try , поскольку Optional находится с монадой Maybe: он черпает вдохновение от него, но адаптирован к идиоме Java ( такие как фактические выбросы исключений даже из нетерминальных операций).

Это некоторые ключевые рекомендации, за которыми следует класс:

  • в отличие от монадического подхода, t игнорировать механизм исключения Java;
  • вместо этого устраняет несоответствие импеданса между исключениями и функциями более высокого порядка; обработка исключений
  • не статически типов (из-за скрытого метания), но всегда безопасна во время выполнения (никогда не проглатывает исключение за исключением явного запроса).

Класс пытается охватить все типичные способы обработки исключения:

  • recover с некоторым кодом обработки, который обеспечивает заменяющее значение;
  • flatRecover, которое, аналогично flatMap, позволяет вернуть новый экземпляр Exceptional, который будет развернут, и состояние текущего экземпляра соответствующим образом обновлено;
  • propagate исключение, выкидывая его из выражения Exceptional и делая вызов propagate объявляющим этот тип исключения;
  • propagate после переноса в другое исключение ( translate it);
  • handle он, в результате чего пустым Exceptional;
  • является особый случай обработки, swallow он содержит пустой блок обработчика.

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


/*
 * Copyright (c) 2015, Marko Topolnik. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

public final class Exceptional
{
  private final T value;
  private final Throwable exception;

  private Exceptional(T value, Throwable exc) {
    this.value = value;
    this.exception = exc;
  }

  public static  Exceptional empty() {
    return new Exceptional<>(null, null);
  }

  public static  Exceptional ofNullable(T value) {
    return value != null ? of(value) : empty();
  }

  public static  Exceptional of(T value) {
    return new Exceptional<>(Objects.requireNonNull(value), null);
  }

  public static  Exceptional ofNullableException(Throwable exception) {
    return exception != null? new Exceptional<>(null, exception) : empty();
  }

  public static  Exceptional ofException(Throwable exception) {
    return new Exceptional<>(null, Objects.requireNonNull(exception));
  }

  public static  Exceptional from(TrySupplier supplier) {
    try {
      return ofNullable(supplier.tryGet());
    } catch (Throwable t) {
      return new Exceptional<>(null, t);
    }
  }

  public static Exceptional fromVoid(TryRunnable task) {
    try {
      task.run();
      return new Exceptional<>(null, null);
    } catch (Throwable t) {
      return new Exceptional<>(null, t);
    }
  }

  public static  Consumer swallow() {
    return e -> {};
  }

  public T get() {
    if (value != null) return value;
    if (exception != null) sneakyThrow(exception);
    throw new NoSuchElementException("No value present");
  }

  public T orElse(T other) {
    if (value != null) return value;
    if (exception != null) sneakyThrow(exception);
    return other;
  }

  public T orElseGet(Supplier other) {
    if (value != null) return value;
    if (exception != null) sneakyThrow(exception);
    return other.get();
  }

  public Stream stream() { 
      return value == null ? Stream.empty() : Stream.of(value); 
  }

  public Exceptional map(Function mapper) {
    Objects.requireNonNull(mapper);
    if (value == null) return new Exceptional<>(null, exception);
    final U u;
    try {
      u = mapper.apply(value);
    } catch (Throwable exc) {
      return new Exceptional<>(null, exc);
    }
    return ofNullable(u);
  }

  public Exceptional flatMap(Function> mapper) {
    Objects.requireNonNull(mapper);
    return value != null ? Objects.requireNonNull(mapper.apply(value)) : empty();
  }

  public Exceptional filter(Predicate predicate) {
    Objects.requireNonNull(predicate);
    if (value == null) return this;
    final boolean b;
    try {
      b = predicate.test(value);
    } catch (Throwable t) {
      return ofException(t);
    }
    return b ? this : empty();
  }

  public  Exceptional recover(
      Class excType, Function mapper)
  {
    Objects.requireNonNull(mapper);
    return excType.isInstance(exception) ? ofNullable(mapper.apply(excType.cast(exception))) : this;
  }

  public  Exceptional recover(
      Iterable> excTypes, Function mapper)
  {
    Objects.requireNonNull(mapper);
    for (Class excType : excTypes)
      if (excType.isInstance(exception))
        return ofNullable(mapper.apply(excType.cast(exception)));
    return this;
  }

  public  Exceptional flatRecover(
      Class excType, Function> mapper)
  {
    Objects.requireNonNull(mapper);
    return excType.isInstance(exception) ? Objects.requireNonNull(mapper.apply(excType.cast(exception))) : this;
  }

  public  Exceptional flatRecover(
      Iterable> excTypes, Function> mapper)
  {
    Objects.requireNonNull(mapper);
    for (Class c : excTypes)
      if (c.isInstance(exception))
        return Objects.requireNonNull(mapper.apply(c.cast(exception)));
    return this;
  }

  public  Exceptional propagate(Class excType) throws E {
    if (excType.isInstance(exception))
      throw excType.cast(exception);
    return this;
  }

  public  Exceptional propagate(Iterable> excTypes) throws E {
    for (Class excType : excTypes)
      if (excType.isInstance(exception))
        throw excType.cast(exception);
    return this;
  }

  public  Exceptional propagate(
      Class excType, Function translator)
  throws F
  {
    if (excType.isInstance(exception))
      throw translator.apply(excType.cast(exception));
    return this;
  }

  public  Exceptional propagate(
      Iterable> excTypes, Function translator)
  throws F
  {
    for (Class excType : excTypes)
      if (excType.isInstance(exception))
        throw translator.apply(excType.cast(exception));
    return this;
  }

  public  Exceptional handle(Class excType, Consumer action) {
    if (excType.isInstance(exception)) {
      action.accept(excType.cast(exception));
      return empty();
    }
    return this;
  }

  public  Exceptional handle(Iterable> excTypes, Consumer action) {
    for (Class excType : excTypes)
      if (excType.isInstance(exception)) {
        action.accept(excType.cast(exception));
        return empty();
      }
    return this;
  }

  public  T orElseThrow(Supplier exceptionSupplier) throws X {
    if (value != null) return value;
    if (exception != null) sneakyThrow(exception);
    throw exceptionSupplier.get();
  }

  public boolean isPresent() {
    return value != null;
  }

  public void ifPresent(Consumer consumer) {
    if (value != null)
      consumer.accept(value);
    if (exception != null) sneakyThrow(exception);
  }

  public boolean isException() {
    return exception != null;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) return true;
    return obj instanceof Exceptional && Objects.equals(value, ((Exceptional)obj).value);
  }

  @Override
  public int hashCode() {
    return Objects.hashCode(value);
  }

  @SuppressWarnings("unchecked")
  private static  void sneakyThrow(Throwable t) throws T {
    throw (T) t;
  }
}

@FunctionalInterface
public interface TrySupplier {
  T tryGet() throws Throwable;
}

@FunctionalInterface
public interface TryRunnable {
  void run() throws Throwable;
}

2
задан Karol Dowbecki 13 July 2018 в 21:46
поделиться

3 ответа

Я смог использовать это, больше не используя параметр includeAll в файле db.changelog-master.yaml. Опция includeAll - это полезный способ быстро начать работу (и обработать все файлы в определенном каталоге), но, похоже, нецелесообразно для регулярного использования. Как упоминалось здесь .

Это то, что я ранее имел в db.changelog-master.yaml, не использую его таким образом.

databaseChangeLog:
    - includeAll:
        path: db/changelog/changes/

Это то, что Я обновил его до:

databaseChangeLog:
    - include:
        file: db/changelog/changes/v0001_users.sql
    - include:
        file: db/changelog/changes/v0002_accounts.sql

. Важно отметить, что я перечисляю каждый отдельный файл, который я хочу включить, в том порядке, в котором я хочу его запустить.

В исходной версии столбец databasechangelog.filename будет отличаться в зависимости от того, как было выполнено приложение:

  • db/changelog/changes/v0001_users.sql - как будет выглядеть столбец при запуске из IntelliJ
  • BOOT-INF/classes/db/changelog/changes/v0001_users.sql, как будет выглядеть столбец при запуске из исполняемого банку.

После внесения изменений оба варианта выше одинаковы и больше не включают BOOT-INF/classes/ в качестве префикса.

Благодаря другим ответам, которые помогли мне указать в правильном направлении!

0
ответ дан mnd 17 August 2018 в 12:11
поделиться

Атрибут logicalFilePath - это именно то, что вы хотите. Я столкнулся с той же проблемой с моими проектами, где я выполнял некоторые части с maven и некоторыми частями с пружинной загрузкой. этот вопрос также может помочь вам.

1
ответ дан bilak 17 August 2018 в 12:11
поделиться
  • 1
    Спасибо за ответ. Я обновил свой вопрос. Возможно ли запустить этот файл без файлов изменений, но вместо этого использовать "inclualAll" в моем файле свойств yaml? Благодарю. – mnd 13 July 2018 в 20:54
  • 2
    Я не совсем понимаю этот вопрос, но если вы хотите запускать все файлы sql, которые находятся в папке ../changes, вы можете пойти с этой настройкой. Но предложите вам изменить логику и не использовать includeAll. У этого есть много недостатков. Прочитайте этот и часть предупреждения – bilak 14 July 2018 в 11:18

Установите logicalFilePath для каждого набора изменений. Это гарантирует, что столбец DATABASECHANGELOG.FILENAME согласован и не зависит от вашего физического каталога проверки файла набора изменений, , как описано в этом сообщении .

1
ответ дан Karol Dowbecki 17 August 2018 в 12:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: