You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot集成Flyway报错:Schema validation: missing table [products]

Spring Boot集成Flyway报错:Schema validation: missing table [products] 解决方法

核心问题

Flyway未执行数据库迁移脚本,导致Hibernate启动时执行ddl-auto=validate校验数据库结构,找不到products表。

针对性解决方案

1. 修正Flyway脚本路径配置

Flyway默认扫描路径为classpath:db/migrations,你将脚本移至db目录并修改配置的操作违背了默认规范,容易导致脚本未被扫描到。

  • 操作步骤:
    1. 将V1__create_users_table.sql和V2__create_products_table.sql移回src/main/resources/db/migrations目录
    2. 修改application.properties中的Flyway路径配置为默认值,或直接删除该配置:
      spring.flyway.locations=classpath:db/migrations
      

2. 开启Flyway基线初始化

如果数据库中尚未创建flyway_schema_history表,Flyway不会自动执行迁移。

  • 操作步骤:
    打开application.properties中注释的基线配置:
    spring.flyway.baseline-on-migrate=true
    
    首次启动时,Flyway会创建基线记录并执行所有迁移脚本。

3. 调整Hibernate与Flyway的执行顺序

Hibernate的校验可能在Flyway迁移完成前执行,导致表不存在。

  • 操作步骤:
    在application.properties中添加延迟JPA初始化的配置:
    spring.jpa.defer-datasource-initialization=true
    
    该配置会让JPA的结构校验延迟到Flyway迁移完成后执行。

4. 验证数据库与脚本可用性

  • 确认spring.datasource.url中的数据库my_db已存在,且数据库账号有创建表的权限
  • 手动执行两个SQL脚本,检查是否存在语法错误(例如外键引用是否有效)

用户提供的相关文件(已翻译)

V1__create_users_table.sql

CREATE TABLE users (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(20) NOT NULL,
    email VARCHAR(255) NOT NULL UNIQUE
);

V2__create_products_table.sql

CREATE TABLE products (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    price DOUBLE NOT NULL,
    user_id BIGINT NOT NULL,
    CONSTRAINT fk_products_user
        FOREIGN KEY (user_id)
        REFERENCES users(id)
        ON DELETE CASCADE
);

application.properties

spring.application.name=demo
# 数据库地址(将'my_db'改为实际数据库名)
spring.datasource.url=jdbc:mysql://localhost:3306/my_db

# MySQL认证信息
spring.datasource.username=root
spring.datasource.password=****

# 驱动类(Spring通常会自动识别,但显式配置更稳妥)
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# Hibernate仅验证结构(不创建)
spring.jpa.hibernate.ddl-auto=validate

# 可选但推荐:显示SQL语句
spring.jpa.show-sql=true

# Flyway配置
spring.flyway.enabled=true
spring.flyway.locations=classpath:db
#spring.flyway.baseline-on-migrate=true

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>4.0.5</version>
       <relativePath/> <!-- 从仓库查找父依赖 -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name/>
    <description/>
    <url/>
    <licenses>
       <license/>
    </licenses>
    <developers>
       <developer/>
    </developers>
    <scm>
       <connection/>
       <developerConnection/>
       <tag/>
       <url/>
    </scm>
    <properties>
       <java.version>26</java.version>
    </properties>
    <dependencies>
       <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-webmvc</artifactId>
       </dependency>

       <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-webmvc-test</artifactId>
          <scope>test</scope>
       </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

        <dependency>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-core</artifactId>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-mysql</artifactId>
            <scope>compile</scope>
        </dependency>
    </dependencies>

    <build>
       <plugins>
          <plugin>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-maven-plugin</artifactId>
          </plugin>
       </plugins>
    </build>

</project>

User实体类

package com.example.demo.user;

import com.example.demo.products.Product;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import jakarta.persistence.*;
import jakarta.validation.constraints.*;

import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    @NotBlank(message = "姓名不能为空")
    @Size(min = 3, max = 20, message = "姓名长度必须在3到20个字符之间")
    private String name;

    @Column(unique = true, nullable = false)
    private String email;

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JsonManagedReference
    private List<Product> products = new ArrayList<>();

    public User() {} // JPA要求的无参构造方法
    public User(String name, String email, List<Product> products) {
        this.name = name;
        this.email = email;
    }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }

    public void setProducts(List<Product> products) {
        this.products = products;
        if (products != null) {
            // 将父实体(当前User)关联到每个子实体(Product)
            for (Product p : products) {
                p.setUser(this);
            }
        }
    }

    public List<Product> getProducts() {
        return this.products;
    }
}

Product实体类

package com.example.demo.products;

import com.example.demo.user.User;
import com.fasterxml.jackson.annotation.JsonBackReference;
import jakarta.persistence.*;

@Entity
@Table(name = "products")
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;

    @Column(nullable = false)
    private String name;

    @Column(nullable = false)
    private double price;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id", nullable = false)
    @JsonBackReference
    private User user;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public double getPrice() { return price; }
    public void setPrice(double price) { this.price = price; }

    public void setUser(User user) {
        this.user = user;
    }
}

内容的提问来源于stack exchange,提问作者Paul_07

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 18:17:26