如何在H2数据库中伪造ENUM列以进行Play单元测试?
如何在H2数据库中伪造ENUM列以进行Play单元测试?
我有一组Play!单元测试,我一直在对H2数据库进行测试。我在我的模型中添加了一些枚举列,现在测试失败,因为用于创建模型表的SQL语句出错。\n错误信息如下:\n
14:42:10,435 ERROR ~ 未知数据类型:"ENUM";SQL语句:
\n通过搜索发现,在H2中有一些模拟枚举的方法(例如:http://groups.google.com/group/h2-database/search?group=h2-database&q=enum&qt_g=Search+this+group)\n将Play设置为使用H2Dialect来进行测试模式并不能解决这个问题。似乎根本原因是H2不支持枚举,或者H2Dialect不知道H2的伪枚举。\n在Play中有没有办法在H2中测试带有枚举的模型?
在H2数据库中,如何伪造ENUM列以进行Play单元测试?
问题的原因是在JPA中,枚举类型通常会被转换为基本类型,这样可以使得代码在不同的数据库中都能正常运行。但是在H2数据库中,不支持直接使用ENUM类型。
解决方法是使用H2数据库的特性来伪造ENUM列。具体的解决方法可以参考以下链接:Map enum in JPA with fixed values?和JPA Enum ORDINAL vs STRING。通过在H2数据库中创建一个与ENUM列对应的表,并使用字符串或整数类型来代替枚举类型,就可以实现伪造ENUM列的效果。
以下是使用字符串类型伪造ENUM列的示例代码:
@Entity @Table(name = "my_entity") public class MyEntity { // 使用字符串类型代替枚举类型 @Column(columnDefinition = "VARCHAR(20)") private String myEnum; // getter and setter }
通过在字段上使用@Column注解,并指定columnDefinition属性为VARCHAR(20),可以将枚举类型转换为字符串类型进行存储。在进行单元测试时,可以使用H2数据库来运行测试,并确保伪造的ENUM列能够正确地工作。
以上就是在H2数据库中伪造ENUM列以进行Play单元测试的解决方案。通过使用H2数据库的特性来伪造ENUM列,可以使得代码在不同的数据库中都能正常运行,同时保持数据库的独立性。
如何在H2数据库中为play单元测试伪造ENUM列?
在spring-boot中,有一个适用于H2的解决方法,但它并不依赖于这两者,因此您可以为play做类似的事情。
请注意,这是一个“伪造”,并不能真正让您完全测试枚举,但它允许您对现有的生产数据库运行测试(您不能随意更改模式),而无需编写整个DDL。
因此,不要让测试框架设置连接字符串用于内存数据库,而是自己配置H2连接字符串。
下面是我案例中的魔法设置:
# 下一行非常重要,它给DDL命名 # H2不支持枚举 # 为了伪造对它们的支持,我们必须声明一个称为enum的域,并将其映射为varchar - 大小是随机选择的,但现在是“足够好”的。 # H2将在hibernate创建模式之前运行此命令,然后模式创建将成功 spring.datasource.url=jdbc:h2:mem:test;MODE=MySQL;INIT=CREATE DOMAIN IF NOT EXISTS enum as VARCHAR(255);DB_CLOSE_ON_EXIT=FALSE
这个魔法是这样的:
CREATE DOMAIN IF NOT EXISTS enum as VARCHAR(255)
这告诉H2将自定义(域)数据类型enum视为varchar - 您可以根据需要更改大小。
它作为一个INIT被执行,这样可以确保它在任何框架对其执行第一部分DDL之前被执行。
因此,在Play!中,设置将是`db.default.jdbcUrl` - 或者您如何定义测试数据库连接(例如作为一个特质)。
如果我想要添加多个create domain语句,该怎么办?我尝试了以下内容,但是出现错误。
spring.datasource.url: jdbc:h2:mem:test;MODE=PostgreSQL;INIT=CREATE DOMAIN IF NOT EXISTS pgsql_enum as VARCHAR(255),CREATE DOMAIN IF NOT EXISTS value_type as VARCHAR(255);DB_CLOSE_ON_EXIT=FALSE
您需要在“CREATE…”语句之间使用“;”作为分隔符,但是您还需要转义“;”,例如“\;”- 在此处查看更多详细信息:stackoverflow.com/questions/5225700/… 如果有很多语句,我建议使用RUNSCRIPT。