繁体   English   中英

用于测试的 Spring Boot H2 db 抛出“找不到表”和“SQL 语法错误”

[英]Spring Boot H2 db for testing throws "Table not found" and "SQL syntax error"

我使用 Spring Boot 开发简单的 Store 应用程序。 我的应用程序使用部署在 docker 容器中的 MySQL 数据库,并且运行良好。 现在我想测试我的应用程序,我得出的结论是H2 in-memory db足以进行测试。 由于我刚开始测试 Spring 应用程序,我遇到了与在 H2 测试数据库中创建表相关的错误。 这些是我遇到的错误

第一个错误

    alter table store_order_items 
       drop 
       foreign key FKikqpbj6xmmyoblsolyhk250tq" via JDBC Statement
    at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67) ~[hibernate-core-5.6.9.Final.jar:5.6.9.Final]
    at org.hibernate.tool.schema.internal.SchemaDropperImpl.applySqlString(SchemaDropperImpl.java 
[...]
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "STORE_ORDER_ITEMS" not found (this database is empty); SQL statement:

第二个错误

org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "
    create table store_order_items (
       Id bigint not null auto_increment,
        quantity bigint,
        order_Id bigint,
        product_Id bigint,
        primary key (Id)
    ) engine=InnoDB" via JDBC Statement
    at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67) ~[hibernate-core-5.6.9.Final.jar:5.6.9.Final]
    at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlString(SchemaCreatorImpl.java:458) ~[hibernate-core-5.6.9.Final.jar:5.6.9.Final]
[...]
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "\000a    create table store_order_items (\000a       Id bigint not null auto_increment,\000a        quantity bigint,\000a        order_Id bigint,\000a        product_Id bigint,\000a        primary key (Id)\000a    ) engine[*]=InnoDB"; expected "identifier"; SQL statement:

src/test/resources/ application.properties

spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;

spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.Driver
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.h2.console.enabled=true


logging.level.org.hibernate.SQL=DEBUG
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

spring.jpa.hibernate.ddl-auto=create
spring.jpa.generate-ddl=true
spring.jpa.defer-datasource-initialization=true

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

测试类

@ExtendWith(SpringExtension.class)
@SpringBootTest
@Transactional
public class UserRepositoryTests {

    private static final Logger LOGGER = Logger.getLogger(UserRepositoryTests.class.getName());

    @Autowired
    private UserRepositoryImpl userRepository;

    @Autowired
    private PasswordEncoder encoder;


    @Test
    void contextLoads() {
        System.out.println(encoder.encode("123"));
// dummy test just to test if tables are built properly
    }

模型/OrderItem.java:

@Entity
@Table(name = "store_order_items")
@NamedQueries({
        @NamedQuery(name=OrderItem.ORDER_ITEM_FIND_ALL, query=OrderItem.ORDER_ITEM_FIND_ALL_JPQL)
})
public class OrderItem {

    // get list of all orders
    public static final String ORDER_ITEM_FIND_ALL = "orderItemAll";
    public static final String ORDER_ITEM_FIND_ALL_JPQL = "SELECT oi FROM OrderItem oi";


    // id will be replaced with two foreign keys
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long Id;

    private Long quantity;

    @JsonBackReference
    @ManyToOne
    private Order order;

    @JsonBackReference
    @ManyToOne
    private Product product;

// getters and setters omitted
}

模型/Order.java:

@Entity
@Table(name = "store_orders")
@NamedQueries({
        @NamedQuery(name=Order.ORDER_FIND_ALL, query=Order.ORDER_FIND_ALL_JPQL),
        @NamedQuery(name=Order.ORDER_SUMMARIES, query=Order.ORDER_SUMMARIES_JPQL)
})
public class Order {

// named queries omitted

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long Id;

    private String orderDate;

    @JsonBackReference
    @ManyToOne
    private User user;

    @JsonManagedReference
    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<OrderItem> orderItems = new ArrayList<>();

// getters and setters omitted
}

我尝试更改列名或使用不同的spring.datasource.url但 id 不起作用。 如果需要,我可以上传更多源代码。

根据我们对评论的对话,使用参数 MODE 对 OP 有效。 所以解决方案是从以下位置更改此配置:

spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;

spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MySQL

注意MODE=MySQL添加到末尾。 这将使 H2 数据库实现忽略某些 MySQL 保留字或将其替换为 (H2) 等效保留字。

Op 还必须更改另一种配置以解决所有问题,另一种是设置ddl-auto设置:

spring.jpa.hibernate.ddl-auto=create

spring.jpa.hibernate.ddl-auto=update

另请注意Evgenij Ryazanov的评论,因此请检查您所在的版本并进行相应的更正:

DATABASE_TO_UPPER=FALSE只能用于 H2 1.4.197 和旧版本,对于 H2 1.4.198 Beta 和更新版本DATABASE_TO_LOWER=TRUE应该使用 MySQL 兼容模式指定,否则所有未加引号的标识符将区分大小写。 经过

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM