From 7e534f30499ec778a4a910a1474d8f56d1a4cecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E7=BF=94?= Date: Wed, 8 Apr 2026 16:57:08 +0800 Subject: [PATCH] =?UTF-8?q?refactor(=E5=AE=A1=E8=AE=A1=E6=97=A5=E5=BF=97):?= =?UTF-8?q?=20=E9=87=8D=E6=9E=84=E5=AE=A1=E8=AE=A1=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=EF=BC=8C=E4=BF=AE=E5=A4=8DSQL=E6=8F=92?= =?UTF-8?q?=E5=85=A5=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题分析:AuditLog领域对象直接继承R2dbcRepository导致SQL插入时缺少entity_id字段 解决方案:参考OperationLog实现模式,新增Entity/Dao/Converter/Repository分层 测试验证:后端启动成功,调试测试通过 --- .../db/converter/AuditLogConverter.java | 87 +++++++++++ .../cn/novalon/manage/db/dao/AuditLogDao.java | 53 +++++++ .../manage/db/entity/AuditLogEntity.java | 135 ++++++++++++++++++ .../db/repository/AuditLogRepository.java | 130 +++++++++++++++++ .../manage/sys/audit/domain/AuditLog.java | 42 +----- .../audit/repository/IAuditLogRepository.java | 13 +- 6 files changed, 416 insertions(+), 44 deletions(-) create mode 100644 novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/converter/AuditLogConverter.java create mode 100644 novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/dao/AuditLogDao.java create mode 100644 novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/entity/AuditLogEntity.java create mode 100644 novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/repository/AuditLogRepository.java diff --git a/novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/converter/AuditLogConverter.java b/novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/converter/AuditLogConverter.java new file mode 100644 index 0000000..c55186f --- /dev/null +++ b/novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/converter/AuditLogConverter.java @@ -0,0 +1,87 @@ +package cn.novalon.manage.db.converter; + +import cn.novalon.manage.sys.audit.domain.AuditLog; +import cn.novalon.manage.db.entity.AuditLogEntity; + +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 审计日志实体转换器 + * + * @author 张翔 + * @date 2026-04-08 + */ +@Component +public class AuditLogConverter { + + public AuditLog toDomain(AuditLogEntity entity) { + if (entity == null) { + return null; + } + AuditLog domain = new AuditLog(); + domain.setId(entity.getId()); + domain.setEntityType(entity.getEntityType()); + domain.setEntityId(entity.getEntityId()); + domain.setOperationType(entity.getOperationType()); + domain.setOperator(entity.getOperator()); + domain.setOperationTime(entity.getOperationTime()); + domain.setBeforeData(entity.getBeforeData()); + domain.setAfterData(entity.getAfterData()); + domain.setChangedFields(entity.getChangedFields()); + domain.setIpAddress(entity.getIpAddress()); + domain.setUserAgent(entity.getUserAgent()); + domain.setDescription(entity.getDescription()); + domain.setCreateBy(entity.getCreateBy()); + domain.setUpdateBy(entity.getUpdateBy()); + domain.setCreatedAt(entity.getCreatedAt()); + domain.setUpdatedAt(entity.getUpdatedAt()); + domain.setDeletedAt(entity.getDeletedAt()); + return domain; + } + + public AuditLogEntity toEntity(AuditLog domain) { + if (domain == null) { + return null; + } + AuditLogEntity entity = new AuditLogEntity(); + entity.setId(domain.getId()); + entity.setEntityType(domain.getEntityType()); + entity.setEntityId(domain.getEntityId()); + entity.setOperationType(domain.getOperationType()); + entity.setOperator(domain.getOperator()); + entity.setOperationTime(domain.getOperationTime()); + entity.setBeforeData(domain.getBeforeData()); + entity.setAfterData(domain.getAfterData()); + entity.setChangedFields(domain.getChangedFields()); + entity.setIpAddress(domain.getIpAddress()); + entity.setUserAgent(domain.getUserAgent()); + entity.setDescription(domain.getDescription()); + entity.setCreateBy(domain.getCreateBy()); + entity.setUpdateBy(domain.getUpdateBy()); + entity.setCreatedAt(domain.getCreatedAt()); + entity.setUpdatedAt(domain.getUpdatedAt()); + entity.setDeletedAt(domain.getDeletedAt()); + return entity; + } + + public List toDomainList(List entities) { + if (entities == null) { + return null; + } + return entities.stream() + .map(this::toDomain) + .collect(Collectors.toList()); + } + + public List toEntityList(List domains) { + if (domains == null) { + return null; + } + return domains.stream() + .map(this::toEntity) + .collect(Collectors.toList()); + } +} diff --git a/novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/dao/AuditLogDao.java b/novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/dao/AuditLogDao.java new file mode 100644 index 0000000..16cafaa --- /dev/null +++ b/novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/dao/AuditLogDao.java @@ -0,0 +1,53 @@ +package cn.novalon.manage.db.dao; + +import cn.novalon.manage.db.entity.AuditLogEntity; +import org.springframework.data.r2dbc.repository.R2dbcRepository; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.time.LocalDateTime; + +/** + * 审计日志数据访问接口 + * + * @author 张翔 + * @date 2026-04-08 + */ +@Repository +public interface AuditLogDao extends R2dbcRepository { + + Flux findByEntityTypeAndDeletedAtIsNull(String entityType); + + Flux findByEntityIdAndDeletedAtIsNull(Long entityId); + + Flux findByEntityTypeAndEntityIdAndDeletedAtIsNull(String entityType, Long entityId); + + Flux findByOperatorAndDeletedAtIsNull(String operator); + + Flux findByOperationTypeAndDeletedAtIsNull(String operationType); + + Flux findByOperationTimeBetweenAndDeletedAtIsNull(LocalDateTime startTime, LocalDateTime endTime); + + Flux findByEntityTypeAndOperationTimeBetweenAndDeletedAtIsNull( + String entityType, + LocalDateTime startTime, + LocalDateTime endTime + ); + + Flux findByOperatorAndOperationTimeBetweenAndDeletedAtIsNull( + String operator, + LocalDateTime startTime, + LocalDateTime endTime + ); + + Mono countByEntityTypeAndDeletedAtIsNull(String entityType); + + Mono countByOperationTypeAndDeletedAtIsNull(String operationType); + + Mono countByOperatorAndDeletedAtIsNull(String operator); + + Mono countByOperationTimeBetweenAndDeletedAtIsNull(LocalDateTime startTime, LocalDateTime endTime); + + Flux findByDeletedAtIsNull(); +} diff --git a/novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/entity/AuditLogEntity.java b/novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/entity/AuditLogEntity.java new file mode 100644 index 0000000..a73dc03 --- /dev/null +++ b/novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/entity/AuditLogEntity.java @@ -0,0 +1,135 @@ +package cn.novalon.manage.db.entity; + +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.Table; + +/** + * 审计日志数据库实体类 + * + * @author 张翔 + * @date 2026-04-08 + */ +@Table("audit_log") +public class AuditLogEntity extends BaseEntity { + + @Column("entity_type") + private String entityType; + + @Column("entity_id") + private Long entityId; + + @Column("operation_type") + private String operationType; + + @Column("operator") + private String operator; + + @Column("operation_time") + private java.time.LocalDateTime operationTime; + + @Column("before_data") + private String beforeData; + + @Column("after_data") + private String afterData; + + @Column("changed_fields") + private String[] changedFields; + + @Column("ip_address") + private String ipAddress; + + @Column("user_agent") + private String userAgent; + + @Column("description") + private String description; + + public String getEntityType() { + return entityType; + } + + public void setEntityType(String entityType) { + this.entityType = entityType; + } + + public Long getEntityId() { + return entityId; + } + + public void setEntityId(Long entityId) { + this.entityId = entityId; + } + + public String getOperationType() { + return operationType; + } + + public void setOperationType(String operationType) { + this.operationType = operationType; + } + + public String getOperator() { + return operator; + } + + public void setOperator(String operator) { + this.operator = operator; + } + + public java.time.LocalDateTime getOperationTime() { + return operationTime; + } + + public void setOperationTime(java.time.LocalDateTime operationTime) { + this.operationTime = operationTime; + } + + public String getBeforeData() { + return beforeData; + } + + public void setBeforeData(String beforeData) { + this.beforeData = beforeData; + } + + public String getAfterData() { + return afterData; + } + + public void setAfterData(String afterData) { + this.afterData = afterData; + } + + public String[] getChangedFields() { + return changedFields; + } + + public void setChangedFields(String[] changedFields) { + this.changedFields = changedFields; + } + + public String getIpAddress() { + return ipAddress; + } + + public void setIpAddress(String ipAddress) { + this.ipAddress = ipAddress; + } + + public String getUserAgent() { + return userAgent; + } + + public void setUserAgent(String userAgent) { + this.userAgent = userAgent; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } +} diff --git a/novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/repository/AuditLogRepository.java b/novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/repository/AuditLogRepository.java new file mode 100644 index 0000000..fdfb246 --- /dev/null +++ b/novalon-manage-api/manage-db/src/main/java/cn/novalon/manage/db/repository/AuditLogRepository.java @@ -0,0 +1,130 @@ +package cn.novalon.manage.db.repository; + +import cn.novalon.manage.sys.audit.domain.AuditLog; +import cn.novalon.manage.sys.audit.repository.IAuditLogRepository; +import cn.novalon.manage.db.converter.AuditLogConverter; +import cn.novalon.manage.db.dao.AuditLogDao; +import cn.novalon.manage.db.entity.AuditLogEntity; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.time.LocalDateTime; + +/** + * 审计日志仓储实现类 + * + * @author 张翔 + * @date 2026-04-08 + */ +@Repository +public class AuditLogRepository implements IAuditLogRepository { + + private final AuditLogDao auditLogDao; + private final AuditLogConverter auditLogConverter; + + public AuditLogRepository(AuditLogDao auditLogDao, AuditLogConverter auditLogConverter) { + this.auditLogDao = auditLogDao; + this.auditLogConverter = auditLogConverter; + } + + @Override + public Mono findById(Long id) { + return auditLogDao.findById(id) + .map(auditLogConverter::toDomain); + } + + @Override + public Mono save(AuditLog auditLog) { + AuditLogEntity entity = auditLogConverter.toEntity(auditLog); + return auditLogDao.save(entity) + .map(auditLogConverter::toDomain); + } + + @Override + public Mono deleteById(Long id) { + return auditLogDao.deleteById(id); + } + + @Override + public Flux findAll() { + return auditLogDao.findByDeletedAtIsNull() + .map(auditLogConverter::toDomain); + } + + @Override + public Flux findByEntityType(String entityType) { + return auditLogDao.findByEntityTypeAndDeletedAtIsNull(entityType) + .map(auditLogConverter::toDomain); + } + + @Override + public Flux findByEntityId(Long entityId) { + return auditLogDao.findByEntityIdAndDeletedAtIsNull(entityId) + .map(auditLogConverter::toDomain); + } + + @Override + public Flux findByEntityTypeAndEntityId(String entityType, Long entityId) { + return auditLogDao.findByEntityTypeAndEntityIdAndDeletedAtIsNull(entityType, entityId) + .map(auditLogConverter::toDomain); + } + + @Override + public Flux findByOperator(String operator) { + return auditLogDao.findByOperatorAndDeletedAtIsNull(operator) + .map(auditLogConverter::toDomain); + } + + @Override + public Flux findByOperationType(String operationType) { + return auditLogDao.findByOperationTypeAndDeletedAtIsNull(operationType) + .map(auditLogConverter::toDomain); + } + + @Override + public Flux findByOperationTimeBetween(LocalDateTime startTime, LocalDateTime endTime) { + return auditLogDao.findByOperationTimeBetweenAndDeletedAtIsNull(startTime, endTime) + .map(auditLogConverter::toDomain); + } + + @Override + public Flux findByEntityTypeAndOperationTimeBetween( + String entityType, + LocalDateTime startTime, + LocalDateTime endTime + ) { + return auditLogDao.findByEntityTypeAndOperationTimeBetweenAndDeletedAtIsNull(entityType, startTime, endTime) + .map(auditLogConverter::toDomain); + } + + @Override + public Flux findByOperatorAndOperationTimeBetween( + String operator, + LocalDateTime startTime, + LocalDateTime endTime + ) { + return auditLogDao.findByOperatorAndOperationTimeBetweenAndDeletedAtIsNull(operator, startTime, endTime) + .map(auditLogConverter::toDomain); + } + + @Override + public Mono countByEntityType(String entityType) { + return auditLogDao.countByEntityTypeAndDeletedAtIsNull(entityType); + } + + @Override + public Mono countByOperationType(String operationType) { + return auditLogDao.countByOperationTypeAndDeletedAtIsNull(operationType); + } + + @Override + public Mono countByOperator(String operator) { + return auditLogDao.countByOperatorAndDeletedAtIsNull(operator); + } + + @Override + public Mono countByOperationTimeBetween(LocalDateTime startTime, LocalDateTime endTime) { + return auditLogDao.countByOperationTimeBetweenAndDeletedAtIsNull(startTime, endTime); + } +} diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/audit/domain/AuditLog.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/audit/domain/AuditLog.java index 22096b3..3e9bac9 100644 --- a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/audit/domain/AuditLog.java +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/audit/domain/AuditLog.java @@ -1,9 +1,7 @@ package cn.novalon.manage.sys.audit.domain; +import cn.novalon.manage.sys.core.domain.BaseDomain; import io.swagger.v3.oas.annotations.media.Schema; -import org.springframework.data.annotation.Id; -import org.springframework.data.relational.core.mapping.Column; -import org.springframework.data.relational.core.mapping.Table; import java.time.LocalDateTime; @@ -13,75 +11,47 @@ import java.time.LocalDateTime; * @author 张翔 * @date 2026-04-01 */ -@Table("audit_log") @Schema(description = "审计日志实体") -public class AuditLog { +public class AuditLog extends BaseDomain { - @Id - @Schema(description = "主键ID") - private Long id; - - @Column("entity_type") @Schema(description = "实体类型(如User, Role等)", example = "User") private String entityType; - @Column("entity_id") @Schema(description = "实体ID", example = "1") private Long entityId; - @Column("operation_type") @Schema(description = "操作类型(CREATE, UPDATE, DELETE)", example = "UPDATE") private String operationType; - @Column("operator") @Schema(description = "操作人", example = "admin") private String operator; - @Column("operation_time") @Schema(description = "操作时间") private LocalDateTime operationTime; - @Column("before_data") @Schema(description = "变更前数据(JSON格式)") private String beforeData; - @Column("after_data") @Schema(description = "变更后数据(JSON格式)") private String afterData; - @Column("changed_fields") @Schema(description = "变更字段列表") private String[] changedFields; - @Column("ip_address") @Schema(description = "IP地址", example = "192.168.1.100") private String ipAddress; - @Column("user_agent") @Schema(description = "用户代理") private String userAgent; - @Column("description") @Schema(description = "操作描述", example = "更新用户信息") private String description; - @Column("created_at") - @Schema(description = "记录创建时间") - private LocalDateTime createdAt; - public AuditLog() { this.operationTime = LocalDateTime.now(); this.createdAt = LocalDateTime.now(); } - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - public String getEntityType() { return entityType; } @@ -169,12 +139,4 @@ public class AuditLog { public void setDescription(String description) { this.description = description; } - - public LocalDateTime getCreatedAt() { - return createdAt; - } - - public void setCreatedAt(LocalDateTime createdAt) { - this.createdAt = createdAt; - } } diff --git a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/audit/repository/IAuditLogRepository.java b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/audit/repository/IAuditLogRepository.java index 98183f9..7c72f6d 100644 --- a/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/audit/repository/IAuditLogRepository.java +++ b/novalon-manage-api/manage-sys/src/main/java/cn/novalon/manage/sys/audit/repository/IAuditLogRepository.java @@ -1,8 +1,6 @@ package cn.novalon.manage.sys.audit.repository; import cn.novalon.manage.sys.audit.domain.AuditLog; -import org.springframework.data.r2dbc.repository.R2dbcRepository; -import org.springframework.stereotype.Repository; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -14,8 +12,15 @@ import java.time.LocalDateTime; * @author 张翔 * @date 2026-04-01 */ -@Repository -public interface IAuditLogRepository extends R2dbcRepository { +public interface IAuditLogRepository { + + Mono findById(Long id); + + Mono save(AuditLog auditLog); + + Mono deleteById(Long id); + + Flux findAll(); Flux findByEntityType(String entityType);