H2 - Postgres 模式支持网络数据类型

Posted

技术标签:

【中文标题】H2 - Postgres 模式支持网络数据类型【英文标题】:H2 - Postgres mode support net data type 【发布时间】:2020-03-16 18:12:58 【问题描述】:

我有一个 DAO 正在访问 Postgres 数据库。我想将 H2 用于我的单元测试 - 一切都很好,除了我正在操作的表有一个带有 inet 数据类型的列 - 所以我得到了例外

未知数据类型:“inet”; SQL 语句:从表中删除 id = ?和 ip_address = ?::inet [50004-200]

自从我使用 H2 以来已经有一段时间了 - 我已经为连接设置了 Postgres 模式:url jdbc:h2:mem:test;MODE=PostgreSQL;DATABASE_TO_LOWER=TRUE

我是否可以在 H2 中执行此查询并支持此数据类型?

【问题讨论】:

考虑使用类似 testcontainers-java 的 postgresql 模块,而不是尝试使用不同的数据库进行单元测试。 @MarkRotteveel 太棒了,谢谢。我尝试了 zonky 嵌入式 Postgres,但它无法在 Jenkins 上构建,并且该项目没有提供任何可操作的输出,因此没有关于哪里出了问题的指导。测试容器完美运行。您能否将其发布为答案,以便我接受它 【参考方案1】:

H2 提供的兼容模式并不完美,它们不能 100% 覆盖所有功能,也不能提供 100% 相同的行为。

我建议您使用PostgreSQL module of testcontainers-java,而不是在您的单元测试中使用不同的数据库,并尝试使其尽可能接近(然后被生产中的差异所困扰)。这允许您为单元测试启动 PostgreSQL docker 映像。

请注意,这会影响性能,因为它可能会比使用 H2 慢一些,因为需要启动 docker 映像。我建议仔细考虑您的测试是否真的需要进入数据库,或者可以摆脱模拟数据,或者至少限制(需要)进入数据库的测试范围。

【讨论】:

工作就像一个魅力 - 我立即注意到时间开销,但这将存在于功能测试层中,因此它不应该太具有破坏性【参考方案2】:

这里最大的问题是您的未知数据类型的表是如何创建的?列 ip_address 应该有一些 H2 已知的其他数据类型。

其实你可以这样创建一个域:

CREATE DOMAIN INET AS VARCHAR;

但是在任何地方都使用相同的数据库系统会更好。

【讨论】:

create table myTable ( ip_address inet, id INT NOT NULL) 是用于创建表的sql - 导致Unknown data type: "inet"; SQL statement 错误 我在上面的表创建之前运行了create domain inet as varchar 并遇到了同样的错误——因为 create 的返回是假的——必须弄清楚该命令失败的原因 create domain inet as varchar; create table myTable ( ip_address inet, id INT NOT NULL); 在 H2 中完成,没有任何异常。 我希望我也有同样的运气。我正在使用 Scalike JDBC - using(inMemoryPool.borrow()) conn => val db: DB = DB(conn) db.localTx implicit session => val inetCreated = sql"""create domain inet as varchar""".execute().apply() println(inetCreated) // false sql"""create table mytable ( ip_address inet, id INT NOT NULL)""".execute.apply() -- 域创建结果为假,后续创建表失败 使用纯 JDBC 和在 H2 控制台中一切正常,但我无法帮助您使用您使用的包装器;我不熟悉它。

以上是关于H2 - Postgres 模式支持网络数据类型的主要内容,如果未能解决你的问题,请参考以下文章

匹配h2 / postgres中的文字百分比?

在服务器模式下使用 H2 可能的最大连接数

在 Play 中,我可以根据数据库类型应用不同的进化吗?

H2 使用在线与数据类型支持

Spring、H2 为不同的环境定义了不同的注解值

Postgres 模式的 SQLAlchemy 支持