Я перенес проект Play с версии 2.3.4 на 2.4.2. В проектах используются JPA (Hibernate) и Evolutions. У меня есть исходный SQL-скрипт Evolutions, который заполняет базу данных некоторыми образцами данных. Этот скрипт сейчас больше не работает, потому что скрипты Evolutions теперь выполняются до того, как Hibernate сгенерирует таблицы, что, очевидно, приводит к ошибке. Это желаемое поведение? Можно ли как-то изменить порядок выполнения?
Play Evolutions и JPA в Play Framework 2.4
Ответы (2)
Эволюция заключается в создании и обновлении базы данных с помощью простых сценариев SQL. Поэтому, если вы используете какой-либо фреймворк, который сам генерирует таблицы данных, например спящий режим, вам нужно отключить эволюции (или отключить автогенерацию и использовать только эволюции)
Заполнять базу данных при запуске
У меня есть аналогичная проблема с Cassandra, что я и сделал - просто создайте код, который читает файл CQL и выполняет его, и запускайте этот код после создания фактических таблиц данных.
Как я вижу, Hibernate уже имеет эту функцию — вам нужно поместить свой собственный код SQL в файл /import.sql
в корне вашего пути к классам:
Если файл с именем import.sql существует в корне пути к классу ('/import.sql'), Hibernate выполнит операторы SQL, считанные из файла после создания схемы базы данных.
У меня была такая же проблема после обновления до 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