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

Docker部署Spring Boot后端:仅UserEntity加载成功,其他实体未生成

问题描述

我正在开发一个Web应用,用Docker构建后端镜像。目前数据库、phpMyAdmin和应用镜像都已成功创建,但只有UserEntity对应的表被创建,其他实体的表无法加载到数据库中。

以下是实体代码:

package org.example.persistence.entity;

import lombok.*;
import javax.persistence.*;

@Entity
@Data
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ExerciseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;
    private String name;
    private String description;
    private String imageUrl;
}

package org.example.persistence.entity;

import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import org.example.domain.MessageStatus;
import javax.persistence.*;
import java.time.LocalDateTime;

@Data
@Entity
@Getter
@Setter
@Table(name = "messages")
public class MessageEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @JoinColumn(name = "sender_id")
    private Long senderId;
    @JoinColumn(name = "receiver_id")
    private Long receiverId;
    @Column(name = "message")
    private String message;
    @Column(name = "date")
    private LocalDateTime date;
    @Enumerated(EnumType.STRING)
    @Column(name = "status")
    private MessageStatus status;
}

package org.example.persistence.entity;

import lombok.*;
import java.time.LocalDate;
import javax.persistence.*;

@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class RequestEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "user_id")
    private Long userId;
    @Column(name = "exercise_id")
    private Long exerciseId;
    @Column(name = "reps")
    private Integer reps;
    @Column(name = "weight")
    private Double weight;
    @Column(name = "date")
    private LocalDate date;
}

package org.example.persistence.entity;

import lombok.*;
import org.example.domain.Role;
import org.hibernate.validator.constraints.Length;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;

@Entity
@Data
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @NotBlank
    @Length(min = 2 ,max = 50)
    private String email;
    @NotBlank
    private String password;
    @NotBlank
    private String firstName;
    @NotBlank
    private String lastName;
    @Column(name = "role", columnDefinition = "ENUM('CUSTOMER', 'TRAINER', 'ADMINISTRATION')")
    @Enumerated(EnumType.STRING)
    private Role role;
}

package org.example.persistence.entity;

import lombok.*;
import javax.persistence.*;
import java.time.LocalDate;

@Entity
@Data
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserExerciseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @ManyToOne
    @JoinColumn(name="user_id", nullable=false)
    private UserEntity user;
    @ManyToOne
    @JoinColumn(name="exercise_id", nullable=false)
    private ExerciseEntity exercise;
    @Column(name = "date")
    private LocalDate date;
}

我的application.properties配置:

##spring.datasource.url=jdbc:mysql://localhost:3331/FitBuddy?useSSL=false&allowPublicKeyRetrieval=true
#spring.datasource.url=jdbc:mysql://host.docker.internal:3331/FitBuddy?useSSL=false&allowPublicKeyRetrieval=true
#
#spring.datasource.username=root
#spring.datasource.password=pass123
###
#spring.jpa.show-sql=true
#spring.jpa.hibernate.ddl-auto=update
#spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
#logging.level.org.hibernate.SQL=DEBUG
#logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
#spring.jpa.open-in-view=false
#jwt.secret=E91E158E4C6656F68B1B5D1C316766DE98D2AD6EF3BFB44F78E9CFCDF5
#
spring.datasource.url=jdbc:mysql://localhost:3331/FitBuddy?useSSL=false&allowPublicKeyRetrieval=true
#spring.datasource.url=jdbc:mysql://db:3306/FitBuddy?useSSL=false&allowPublicKeyRetrieval=true
spring.datasource.username=Stoyan
spring.datasource.password=pass123
spring.jpa.properties.hibernate.packagesToScan=org.example.persistence.entity

spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

spring.jpa.open-in-view=false

jwt.secret=E91E158E4C6656F68B1B5D1C316766DE98D2AD6EF3BFB44F78E9CFCDF5

docker-compose.yml配置:

version: '3.8'

services:
  db:
    image: mysql:latest
    ports:
      - 3306:3306
    environment:
      MYSQL_DATABASE: FitBuddy
      MYSQL_USER: Stoyan
      MYSQL_PASSWORD: pass123
      MYSQL_ROOT_PASSWORD: pass123

  phpmyadmin:
    image: phpmyadmin/phpmyadmin:latest
    depends_on:
      - db
    environment:
      PMA_HOST: db
    ports:
      - 7098:80

  app:
    build:
      dockerfile: Dockerfile
    environment:
      DB_HOST: db
      DB_PORT: 3306
      DB_USER: Stoyan
      DB_PASSWORD: pass123
      DB_NAME: FitBuddy
    depends_on:
      - db
    ports:
      - "8080:8080"
可能的原因及解决办法
  • 数据库连接配置不匹配
    你在docker-compose中给app服务配置了DB_HOST: db等环境变量,但application.properties里硬编码了spring.datasource.url=jdbc:mysql://localhost:3331/FitBuddy——在Docker容器内,localhost指向容器自身,而不是宿主机或db容器,同时db容器的端口是3306,不是3331。这会导致应用连错数据库(甚至连不上),UserEntity的表大概率是本地开发时创建的,并非Docker环境生成。
    解决:修改application.properties,用环境变量动态读取数据库配置:

    spring.datasource.url=jdbc:mysql://${DB_HOST}:${DB_PORT}/${DB_NAME}?useSSL=false&allowPublicKeyRetrieval=true
    spring.datasource.username=${DB_USER}
    spring.datasource.password=${DB_PASSWORD}
    
  • 实体扫描范围未覆盖全量实体
    虽然配置了spring.jpa.properties.hibernate.packagesToScan,但Spring Boot有时更依赖@EntityScan注解来识别实体类。如果你的主应用类(带@SpringBootApplication的类)不在org.example包下,默认扫描范围不会包含org.example.persistence.entity,导致仅UserEntity被扫描到(可能是之前本地调试时的残留)。
    解决:在主应用类上添加注解:

    @SpringBootApplication
    @EntityScan(basePackages = "org.example.persistence.entity")
    public class YourApplication {
        public static void main(String[] args) {
            SpringApplication.run(YourApplication.class, args);
        }
    }
    
  • Docker容器启动顺序导致数据库未就绪
    depends_on仅保证db容器先启动,但不保证MySQL服务完全初始化完成。如果应用启动时数据库还在启动过程中,Hibernate初始化会失败,无法创建所有表。
    解决:

    1. 在app服务中添加健康检查,等待MySQL就绪:
      app:
        build:
          dockerfile: Dockerfile
        environment:
          DB_HOST: db
          DB_PORT: 3306
          DB_USER: Stoyan
          DB_PASSWORD: pass123
          DB_NAME: FitBuddy
        depends_on:
          - db
        ports:
          - "8080:8080"
        healthcheck:
          test: ["CMD-SHELL", "mysqladmin ping -h db -u Stoyan -ppass123"]
          interval: 10s
          timeout: 5s
          retries: 5
      
    2. 或者在应用中配置连接池重试:
      spring.datasource.hikari.connection-test-query=SELECT 1
      spring.datasource.hikari.maximum-pool-size=10
      spring.datasource.hikari.connection-timeout=30000
      
  • 枚举类或实体关联的潜在问题
    检查Role和MessageStatus枚举类的定义是否与实体中的配置一致:比如UserEntity中role的columnDefinition是ENUM('CUSTOMER', 'TRAINER', 'ADMINISTRATION'),要确保Role枚举的取值完全匹配这些字符串。另外UserExerciseEntity中的@ManyToOne关联,如果关联的实体未被扫描到,也会导致该表无法创建。
    解决:核对枚举类的常量名称与实体中columnDefinition的取值完全一致,确保关联的实体类都被正确扫描。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 13:24:55