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

JHipster实体继承AbstractAuditingEntity后审计字段未同步至PostgreSQL

JHipster自定义Indicator实体审计字段未同步到PostgreSQL的解决办法

针对你遇到的Indicator实体继承AbstractAuditingEntity后,审计字段未同步到PostgreSQL数据库的问题,以下是几个排查和解决方向:


1. 确认JPA自动建表配置

检查application.yml或application.properties中的Hibernate DDL配置,确保设置为能更新表结构的模式:

spring:
  jpa:
    hibernate:
      ddl-auto: update

注意:生产环境建议设置为none,通过Liquibase/Flyway管理数据库迁移。

2. 启用JPA审计功能

主启动类必须添加@EnableJpaAuditing注解,否则AuditingEntityListener不会生效,审计字段也不会被处理:

@SpringBootApplication
@EnableJpaAuditing
public class YourApplication {
    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }
}

3. 使用JHipster推荐的Liquibase生成迁移脚本

如果数据库表已存在,Hibernate的update模式可能无法自动添加字段,这时候用Liquibase生成并执行迁移脚本是更可靠的方式:

  • 生成差异脚本:
    # Maven项目
    ./mvnw liquibase:diff
    # Gradle项目
    ./gradlew liquibaseDiffChangelog
    
  • 脚本生成在src/main/resources/config/liquibase/changelog目录下,检查是否包含添加created_by、created_date等字段的语句
  • 执行迁移更新数据库:
    # Maven项目
    ./mvnw liquibase:update
    # Gradle项目
    ./gradlew liquibaseUpdate
    

4. 调整审计字段的约束

如果原表已存在,添加nullable=false的字段会失败(现有数据无值),可以先修改AbstractAuditingEntity中的字段注解,去掉nullable=false:

@CreatedBy
@Column(name = "created_by", length = 50, updatable = false)
private String createdBy;

等字段创建并补全数据后,再重新添加nullable=false约束。

5. 清理缓存并重启

清理项目编译缓存,确保Hibernate加载最新的实体元数据:

# Maven项目
./mvnw clean
# Gradle项目
./gradlew clean

然后重启应用。


附:你提供的相关代码

AbstractAuditingEntity基类

@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties(value = { "createdBy", "createdDate", "lastModifiedBy", "lastModifiedDate" }, allowGetters = true)
public abstract class AbstractAuditingEntity<T> implements Serializable {

    private static final long serialVersionUID = 1L;

    public abstract T getId();

    @CreatedBy
    @Column(name = "created_by", nullable = false, length = 50, updatable = false)
    private String createdBy;

    @CreatedDate
    @Column(name = "created_date", updatable = false)
    private Instant createdDate = Instant.now();

    @LastModifiedBy
    @Column(name = "last_modified_by", length = 50)
    private String lastModifiedBy;

    @LastModifiedDate
    @Column(name = "last_modified_date")
    private Instant lastModifiedDate = Instant.now();

    // Getters and Setters
    public String getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(String createdBy) {
        this.createdBy = createdBy;
    }

    public Instant getCreatedDate() {
        return createdDate;
    }

    public void setCreatedDate(Instant createdDate) {
        this.createdDate = createdDate;
    }

    public String getLastModifiedBy() {
        return lastModifiedBy;
    }

    public void setLastModifiedBy(String lastModifiedBy) {
        this.lastModifiedBy = lastModifiedBy;
    }

    public Instant getLastModifiedDate() {
        return lastModifiedDate;
    }

    public void setLastModifiedDate(Instant lastModifiedDate) {
        this.lastModifiedDate = lastModifiedDate;
    }
}

Indicator实体类

@Entity
@Table(name = "indicator")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@SuppressWarnings("common-java:DuplicatedBlocks")
public class Indicator extends AbstractAuditingEntity<Long> implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
    @SequenceGenerator(name = "sequenceGenerator")
    @Column(name = "id")
    private Long id;

    @NotNull
    @Column(name = "code", nullable = false, unique = true)
    private Integer code;

    @NotNull
    @Size(max = 50)
    @Column(name = "title", length = 50, nullable = false)
    private String title;

    @NotNull
    @Size(max = 50)
    @Column(name = "titlear", length = 50, nullable = false)
    private String titlear;

    @NotNull
    @Size(max = 50)
    @Column(name = "titlefr", length = 50, nullable = false)
    private String titlefr;

    @Size(max = 500)
    @Column(name = "description", length = 500)
    private String description;

    @Size(max = 500)
    @Column(name = "descriptionar", length = 500)
    private String descriptionar;

    @Size(max = 500)
    @Column(name = "descriptionfr", length = 500)
    private String descriptionfr;

    @NotNull
    @Column(name = "rating", nullable = false)
    private Integer rating;

    @ManyToMany(mappedBy = "indicators")
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    @JsonIgnoreProperties(value = { "indicators" }, allowSetters = true)
    private Set<Competency> competencies = new HashSet<>();

    // Getters and Setters
    public Long getId() {
        return this.id;
    }

    public Indicator id(Long id) {
        this.setId(id);
        return this;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Integer getCode() {
        return this.code;
    }

    public Indicator code(Integer code) {
        this.setCode(code);
        return this;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getTitle() {
        return this.title;
    }

    public Indicator title(String title) {
        this.setTitle(title);
        return this;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getTitlear() {
        return this.titlear;
    }

    public Indicator titlear(String titlear) {
        this.setTitlear(titlear);
        return this;
    }

    public void setTitlear(String titlear) {
        this.titlear = titlear;
    }

    public String getTitlefr() {
        return this.titlefr;
    }

    public Indicator titlefr(String titlefr) {
        this.setTitlefr(titlefr);
        return this;
    }

    public void setTitlefr(String titlefr) {
        this.titlefr = titlefr;
    }

    public String getDescription() {
        return this.description;
    }

    public Indicator description(String description) {
        this.setDescription(description);
        return this;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getDescriptionar() {
        return this.descriptionar;
    }

    public Indicator descriptionar(String descriptionar) {
        this.setDescriptionar(descriptionar);
        return this;
    }

    public void setDescriptionar(String descriptionar) {
        this.descriptionar = descriptionar;
    }

    public String getDescriptionfr() {
        return this.descriptionfr;
    }

    public Indicator descriptionfr(String descriptionfr) {
        this.setDescriptionfr(descriptionfr);
        return this;
    }

    public void setDescriptionfr(String descriptionfr) {
        this.descriptionfr = descriptionfr;
    }

    public Integer getRating() {
        return this.rating;
    }

    public Indicator rating(Integer rating) {
        this.setRating(rating);
        return this;
    }

    public void setRating(Integer rating) {
        this.rating = rating;
    }

    public Set<Competency> getCompetencies() {
        return this.competencies;
    }

    public void setCompetencies(Set<Competency> competencies) {
        if (this.competencies != null) {
            this.competencies.forEach(i -> i.removeIndicator(this));
        }
        if (competencies != null) {
            competencies.forEach(i -> i.addIndicator(this));
        }
        this.competencies = competencies;
    }

    public Indicator competencies(Set<Competency> competencies) {
        this.setCompetencies(competencies);
        return this;
    }

    public Indicator addCompetency(Competency competency) {
        this.competencies.add(competency);
        competency.getIndicators().add(this);
        return this;
    }

    public Indicator removeCompetency(Competency competency) {
        this.competencies.remove(competency);
        competency.getIndicators().remove(this);
        return this;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof Indicator)) {
            return false;
        }
        return id != null && id.equals(((Indicator) o).id);
    }

    @Override
    public int hashCode() {
        return getClass().hashCode();
    }

    @Override
    public String toString() {
        return "Indicator{" +
            "id=" + getId() +
            ", code=" + getCode() +
            ", title='" + getTitle() + "'" +
            ", titlear='" + getTitlear() + "'" +
            ", titlefr='" + getTitlefr() + "'" +
            ", description='" + getDescription() + "'" +
            ", descriptionar='" + getDescriptionar() + "'" +
            ", descriptionfr='" + getDescriptionfr() + "'" +
            ", rating=" + getRating() +
            "}";
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 15:25:35