我将 Play 项目从 2.3.4 版本迁移到 2.4.2。这些项目使用 JPA (Hibernate) 和 Evolutions。我有一个初始的 Evolutions SQL 脚本,它用一些示例数据填充数据库。这个脚本现在不再工作了,因为 Evolutions 脚本现在在 Hibernate 生成表之前执行,这显然会导致错误。这是理想的行为吗?有没有办法改变执行顺序?
2 回答
从 2.3 升级到 2.4 后我遇到了同样的问题我的测试没有工作,因为我使用 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 演变后调用了 hibernate。为了解决这个问题,我在我的集成器配置中关闭了自动进化
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);
});
}
我不同意我们不能同时使用 Evolutions 和 Hibernate。我发现将两者都用于集成测试是一个完美的解决方案。如果您只想使用进化,问题是进化与数据库相关,因此 MySQL 进化不适用于 H2 db。第二个原因是我对不同的测试用例使用了不同的演进,我需要为每个演进复制粘贴所有带有方案的脚本。
我相信使用 Hibernate 为集成测试创建方案是完全可以的,并且 2.4 的更改是一个突破性的更改,应该记录在案。
这是我的存储库,其中包含 play 2.6 的工作示例,但它也应该适用于 play >= 2.4 githubrepository
Evolutions 是关于通过纯 SQL 脚本创建和更新数据库的。因此,如果您使用一些自己生成数据表的框架,例如休眠,那么您需要关闭进化(或关闭自动生成并仅使用进化)
启动时填充数据库
我在 Cassandra 上有一个类似的问题,我做了什么 - 只需创建一个读取 CQL 文件并执行它的代码,并在创建实际数据表后运行此代码。
正如我所见,Hibernate 已经具有此功能 - 您需要将自定义 SQL 代码放入/import.sql
类路径根目录中的文件中:
如果类路径('/import.sql')的根目录中存在一个名为 import.sql 的文件,Hibernate 将在创建数据库模式后执行从该文件中读取的 SQL 语句。