未知数据类型 "JSONB" 当 运行 使用 H2 数据库进行 play slick 测试时
Unknown data type "JSONB" when running tests in play slick with H2 Database
我有进化问题未知数据类型:"JSONB"当运行使用
在playframework中测试时
- 适用于 scala 的 playframework v2.6.6
- play-slick v3.0.2
- play-slick-evolutions v3.0.2
- postgresql - 42.0.0
- h2 数据库 - 1.4.194
我的 H2DbConnector 如下所示:
import entities.StubData._
import org.scalatest.{BeforeAndAfterAll, FunSuite}
import play.api.db.DBApi
import play.api.db.evolutions.Evolutions
import play.api.inject.guice.GuiceApplicationBuilder
trait H2DbConnector extends FunSuite with BeforeAndAfterAll {
val appBuilder = new GuiceApplicationBuilder()
.configure(configuration)
val injector = appBuilder.injector
lazy val databaseApi = injector.instanceOf[DBApi]
override def beforeAll() = {
Evolutions.applyEvolutions(databaseApi.database("default"))
}
override def afterAll() = {
Evolutions.cleanupEvolutions(databaseApi.database("default"))
}
}
在application.test.conf
slick.dbs.default.driver = "slick.driver.H2Driver$"
slick.dbs.default.db.driver = "org.h2.Driver"
slick.dbs.default.db.url = "jdbc:h2:mem:play;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=FALSE"
我在 evolutions 2.sql 文件中有一行有问题
ALTER TABLE "Messages" ADD COLUMN "metaJson" JSONB NULL;
当我 运行 dao 测试时出现类似
的错误
2017-12-21 16:08:40,409 [error] p.a.d.e.DefaultEvolutionsApi - Unknown data type: "JSONB"; SQL statement:
ALTER TABLE "Messages" ADD COLUMN "metaJson" JSONB NULL [50004-194] [ERROR:50004, SQLSTATE:HY004]
[info] OptoutsDaoTest *** ABORTED ***
[info] play.api.db.evolutions.InconsistentDatabase: Database 'default' is in an inconsistent state![An evolution has not been applied properly. Please check the problem and resolve it manually before marking it as resolved.]
[info] at play.api.db.evolutions.DatabaseEvolutions.$anonfun$checkEvolutionsState(EvolutionsApi.scala:285)
[info] at play.api.db.evolutions.DatabaseEvolutions.$anonfun$checkEvolutionsState$adapted(EvolutionsApi.scala:270)
[info] at play.api.db.evolutions.DatabaseEvolutions.executeQuery(EvolutionsApi.scala:317)
[info] at play.api.db.evolutions.DatabaseEvolutions.checkEvolutionsState(EvolutionsApi.scala:270)
[info] at play.api.db.evolutions.DatabaseEvolutions.evolve(EvolutionsApi.scala:239)
[info] at play.api.db.evolutions.Evolutions$.applyEvolutions(Evolutions.scala:193)
[info] at H2DbConnector.beforeAll(H2DbConnector.scala:15)
[info] at H2DbConnector.beforeAll$(H2DbConnector.scala:14)
[info] at OptoutsDaoTest.beforeAll(OptoutsDaoTest.scala:5)
[info] at org.scalatest.BeforeAndAfterAll.liftedTree1(BeforeAndAfterAll.scala:212)
[info] ...
你能帮我解决这个问题吗?
H2 不支持 JSONB
列类型。
所有支持的列类型Supported datatypes of H2
尝试在测试中也使用 postgres 或编写两个数据库都能理解的标准 SQL 语句。
你不能使用 PostgreSQL 进行单元测试,因为你正在连接到某些东西,单元测试应该只中继内存中测试,因为它会被你的构建触发,并且构建服务器不太可能访问任何物理数据库,您可能需要另一种方法来模拟您的数据并避免数据库从中访问它,或者将您的数据类型更改为字符串 [] 并将其封装以生成 JSON
我最近在使用 JSONB 和 H2 时也遇到了这个问题。我通过创建一个 JSONB 的别名到 JSON 来解决它,并且只在 H2 的测试配置文件中使用它 运行。
CREATE TYPE "JSONB" AS json;
它不是 JSONB 但 JSONB 与 JSON 的区别(至少在 postgres 中)本质上是阅读的性能,出于测试目的,这不是真的很重要(非常重要)。
也许这个例子也有帮助:
这是一个使用 flyway 的示例。创建一个 sql 条目以在 /resources/db/tests 上为 jsonb 创建一个别名类型,运行 仅在测试配置文件上。
我们使用的是 spring 所以这里是 application.yml 的入口:
spring:
profiles: mytest
datasource:
continueOnError: false
url: jdbc:h2:mem:myapp-db;DB_CLOSE_ON_EXIT=FALSE;MODE=PostgreSQL;DATABASE_TO_LOWER=TRUE
flyway:
enabled: true
locations: classpath:db/migration, classpath:db/tests
[......]
这是 ${project.dir}/resources/db/
的列表
神奇之处在于:
在文件的内容中,我创建了一个名为 JSONB 的类型,它基本上是 JSON 类型的别名。注意:据我所知,大写字母是必需的(特别是当您在创建 table 时引用它时)因为 H2 似乎自动将类型名称更改为大写字母:
CREATE TYPE "JSONB" AS json;
下面是创建 table 类型的示例:
CREATE TABLE "XXX" (
id BIGSERIAL PRIMARY KEY,
my_json_column_name JSONB NOT NULL
);
在 hibernate 方面,我使用 hibernate-types52 中的 JsonBinaryType 类型查看更多信息 link。
@Data
@TypeDef(name = "jsonb", typeClass = com.vladmihalcea.hibernate.type.json.JsonBinaryType.class)
@Entity(name = "XXX")
@Table(name = "XXX")
public class XXX {
@Type(type = "jsonb")
@Column(name = "my_json_column_name", nullable = false)
private String myJsonColumnName;
//OR
@Type(type = "jsonb")
@Column(name = "my_json_column_name", nullable = false)
private List<MYCustomTypeThatMatchesJsonObject> myJsonColumnName;
}
希望对大家有所帮助。它对我有用。
更新于 2020 年 7 月 13 日
我停止在我的项目中使用 H2,并开始使用 testcontainers。设置非常简单,您可以在真实的数据库环境中进行测试。
对于那些即使在定义了 TypeDef 之后在 H2 和 PostgreSQL 数据库中仍然有这个问题的人...等,请查看我的回答 here
我有进化问题未知数据类型:"JSONB"当运行使用
在playframework中测试时- 适用于 scala 的 playframework v2.6.6
- play-slick v3.0.2
- play-slick-evolutions v3.0.2
- postgresql - 42.0.0
- h2 数据库 - 1.4.194
我的 H2DbConnector 如下所示:
import entities.StubData._
import org.scalatest.{BeforeAndAfterAll, FunSuite}
import play.api.db.DBApi
import play.api.db.evolutions.Evolutions
import play.api.inject.guice.GuiceApplicationBuilder
trait H2DbConnector extends FunSuite with BeforeAndAfterAll {
val appBuilder = new GuiceApplicationBuilder()
.configure(configuration)
val injector = appBuilder.injector
lazy val databaseApi = injector.instanceOf[DBApi]
override def beforeAll() = {
Evolutions.applyEvolutions(databaseApi.database("default"))
}
override def afterAll() = {
Evolutions.cleanupEvolutions(databaseApi.database("default"))
}
}
在application.test.conf
slick.dbs.default.driver = "slick.driver.H2Driver$"
slick.dbs.default.db.driver = "org.h2.Driver"
slick.dbs.default.db.url = "jdbc:h2:mem:play;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=FALSE"
我在 evolutions 2.sql 文件中有一行有问题
ALTER TABLE "Messages" ADD COLUMN "metaJson" JSONB NULL;
当我 运行 dao 测试时出现类似
的错误2017-12-21 16:08:40,409 [error] p.a.d.e.DefaultEvolutionsApi - Unknown data type: "JSONB"; SQL statement:
ALTER TABLE "Messages" ADD COLUMN "metaJson" JSONB NULL [50004-194] [ERROR:50004, SQLSTATE:HY004]
[info] OptoutsDaoTest *** ABORTED ***
[info] play.api.db.evolutions.InconsistentDatabase: Database 'default' is in an inconsistent state![An evolution has not been applied properly. Please check the problem and resolve it manually before marking it as resolved.]
[info] at play.api.db.evolutions.DatabaseEvolutions.$anonfun$checkEvolutionsState(EvolutionsApi.scala:285)
[info] at play.api.db.evolutions.DatabaseEvolutions.$anonfun$checkEvolutionsState$adapted(EvolutionsApi.scala:270)
[info] at play.api.db.evolutions.DatabaseEvolutions.executeQuery(EvolutionsApi.scala:317)
[info] at play.api.db.evolutions.DatabaseEvolutions.checkEvolutionsState(EvolutionsApi.scala:270)
[info] at play.api.db.evolutions.DatabaseEvolutions.evolve(EvolutionsApi.scala:239)
[info] at play.api.db.evolutions.Evolutions$.applyEvolutions(Evolutions.scala:193)
[info] at H2DbConnector.beforeAll(H2DbConnector.scala:15)
[info] at H2DbConnector.beforeAll$(H2DbConnector.scala:14)
[info] at OptoutsDaoTest.beforeAll(OptoutsDaoTest.scala:5)
[info] at org.scalatest.BeforeAndAfterAll.liftedTree1(BeforeAndAfterAll.scala:212)
[info] ...
你能帮我解决这个问题吗?
H2 不支持 JSONB
列类型。
所有支持的列类型Supported datatypes of H2
尝试在测试中也使用 postgres 或编写两个数据库都能理解的标准 SQL 语句。
你不能使用 PostgreSQL 进行单元测试,因为你正在连接到某些东西,单元测试应该只中继内存中测试,因为它会被你的构建触发,并且构建服务器不太可能访问任何物理数据库,您可能需要另一种方法来模拟您的数据并避免数据库从中访问它,或者将您的数据类型更改为字符串 [] 并将其封装以生成 JSON
我最近在使用 JSONB 和 H2 时也遇到了这个问题。我通过创建一个 JSONB 的别名到 JSON 来解决它,并且只在 H2 的测试配置文件中使用它 运行。
CREATE TYPE "JSONB" AS json;
它不是 JSONB 但 JSONB 与 JSON 的区别(至少在 postgres 中)本质上是阅读的性能,出于测试目的,这不是真的很重要(非常重要)。
也许这个例子也有帮助:
这是一个使用 flyway 的示例。创建一个 sql 条目以在 /resources/db/tests 上为 jsonb 创建一个别名类型,运行 仅在测试配置文件上。
我们使用的是 spring 所以这里是 application.yml 的入口:
spring:
profiles: mytest
datasource:
continueOnError: false
url: jdbc:h2:mem:myapp-db;DB_CLOSE_ON_EXIT=FALSE;MODE=PostgreSQL;DATABASE_TO_LOWER=TRUE
flyway:
enabled: true
locations: classpath:db/migration, classpath:db/tests
[......]
这是 ${project.dir}/resources/db/
的列表神奇之处在于:
在文件的内容中,我创建了一个名为 JSONB 的类型,它基本上是 JSON 类型的别名。注意:据我所知,大写字母是必需的(特别是当您在创建 table 时引用它时)因为 H2 似乎自动将类型名称更改为大写字母:
CREATE TYPE "JSONB" AS json;
下面是创建 table 类型的示例:
CREATE TABLE "XXX" (
id BIGSERIAL PRIMARY KEY,
my_json_column_name JSONB NOT NULL
);
在 hibernate 方面,我使用 hibernate-types52 中的 JsonBinaryType 类型查看更多信息 link。
@Data
@TypeDef(name = "jsonb", typeClass = com.vladmihalcea.hibernate.type.json.JsonBinaryType.class)
@Entity(name = "XXX")
@Table(name = "XXX")
public class XXX {
@Type(type = "jsonb")
@Column(name = "my_json_column_name", nullable = false)
private String myJsonColumnName;
//OR
@Type(type = "jsonb")
@Column(name = "my_json_column_name", nullable = false)
private List<MYCustomTypeThatMatchesJsonObject> myJsonColumnName;
}
希望对大家有所帮助。它对我有用。
更新于 2020 年 7 月 13 日
我停止在我的项目中使用 H2,并开始使用 testcontainers。设置非常简单,您可以在真实的数据库环境中进行测试。
对于那些即使在定义了 TypeDef 之后在 H2 和 PostgreSQL 数据库中仍然有这个问题的人...等,请查看我的回答 here