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
相关产品推荐
相关产品推荐

