Play Evolutions и JPA в Play Framework 2.4

Я перенес проект Play с версии 2.3.4 на 2.4.2. В проектах используются JPA (Hibernate) и Evolutions. У меня есть исходный SQL-скрипт Evolutions, который заполняет базу данных некоторыми образцами данных. Этот скрипт сейчас больше не работает, потому что скрипты Evolutions теперь выполняются до того, как Hibernate сгенерирует таблицы, что, очевидно, приводит к ошибке. Это желаемое поведение? Можно ли как-то изменить порядок выполнения?


person linsenfips    schedule 19.07.2015    source источник


Ответы (2)


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

Заполнять базу данных при запуске

У меня есть аналогичная проблема с Cassandra, что я и сделал - просто создайте код, который читает файл CQL и выполняет его, и запускайте этот код после создания фактических таблиц данных.

Как я вижу, Hibernate уже имеет эту функцию — вам нужно поместить свой собственный код SQL в файл /import.sql в корне вашего пути к классам:

Если файл с именем import.sql существует в корне пути к классу ('/import.sql'), Hibernate выполнит операторы SQL, считанные из файла после создания схемы базы данных.

person Andriy Kuba    schedule 11.11.2015
comment
Спасибо за подробный ответ, но не соглашусь. В документе Play говорится: Когда вы используете реляционную базу данных, вам нужен способ отслеживать и организовывать эволюцию схемы вашей базы данных. Это не говорит, как получить доступ к этой базе данных. На мой взгляд, Evolutions был идеальным дополнением к Hibernate, потому что Hibernate имеет лишь ограниченные возможности миграции. И дело в том, что это работало годами в Play, так что я считаю это багом. - person linsenfips; 16.11.2015
comment
Вы написали, что Hibernate генерирует таблицы, это означает, что Hibernate организует вашу базу данных. Вам нужно использовать только одну механику обновления базы данных — эволюцию или генерацию спящих таблиц. Если вы хотите использовать эволюцию, отключите создание таблиц Hibernate: stackoverflow.com/questions/221379/. - person Andriy Kuba; 16.11.2015
comment
ПРЕДУПРЕЖДЕНИЕ. Мы видели, как пользователи Hibernate пытались использовать SchemaUpdate для автоматического обновления схемы рабочей базы данных. Это может быстро закончиться катастрофой и не будет разрешено вашим администратором баз данных. - person Andriy Kuba; 16.11.2015

У меня была такая же проблема после обновления до 2.4 с 2.3. Мои тесты не работали, так как я использовал Hibernate для создания всех таблиц в H2 в БД памяти и воспроизведения эволюции для подготовки БД с данными для тестовых случаев.

Моя тестовая база была похожа на

public abstract class TestServerBase extends WithServer {
    public static String H2_URL =  "jdbc:h2:mem:glamazon;MODE=MySQL;REFERENTIAL_INTEGRITY=False";

    public abstract String getDb();

    @Override
    protected FakeApplication provideFakeApplication() {
        final String db = getDb();
        final Map config = new HashMap();
        config.put(String.format("db.%s.driver",db), "org.h2.Driver");
        config.put(String.format("db.%s.url",db), H2_URL);
        config.put(String.format("db.%s.user",db), "");
        config.put(String.format("db.%s.password",db), "");
        config.put(String.format("db.%s.jndiName",db), "DefaultDS");
        return Helpers.fakeApplication(config);
    }
}

Начиная с play 2.4 что-то изменилось, и спящий режим был назван в честь эволюции игры. Чтобы решить эту проблему, я отключил автоматическую эволюцию в своей конфигурации интеграторов.

play.evolutions.enabled=false

и я придумал новый метод для моей TestServerBase

@Before
public void runEvolutions(){
    final Database db = Databases.createFrom(getDb(),"org.h2.Driver", H2_URL);
    JPA.withTransaction(() ->{
        Evolutions.applyEvolutions(db);
    });
}

@After
public void deleteEvolutions(){
    final Database db = Databases.createFrom(getDb(),"org.h2.Driver", H2_URL);
    JPA.withTransaction(() ->{
        Evolutions.cleanupEvolutions(db);
    });

}

Я не согласен с тем, что мы не можем использовать эволюции и Hibernate вместе. Я нашел, что использование обоих для интеграционных тестов является идеальным решением. Если вы хотите использовать только эволюции, проблема в том, что эволюции связаны с БД, поэтому эволюции MySQL не работают с H2 db. Вторая причина в том, что я использовал разные эволюции для разных тестовых случаев, и мне нужно было бы скопировать и вставить все скрипты со схемой для каждой эволюции.

Я считаю, что использование Hibernate для создания схемы интеграционных тестов совершенно нормально, а изменение 2.4 — это критическое изменение, которое должно было быть задокументировано.

Вот мой репозиторий с рабочим примером для play 2.6, но он должен работать и с play >= 2.4 githubrepository

person Marious    schedule 29.10.2018