fix(flyway): 修复Flyway初始化问题并完善测试覆盖

- 修复数据库连接配置,确保Flyway迁移正常执行
- 完善Repository接口的查询方法,支持审计日志和操作日志查询
- 增强Service层业务逻辑,优化用户、角色、菜单等核心功能
- 补充单元测试和集成测试,确保系统稳定性
- 添加测试数据初始化脚本,支持自动化测试环境搭建

关联任务:Flyway数据库迁移优化
This commit was merged in pull request #5.
This commit is contained in:
张翔
2026-04-24 15:01:59 +08:00
parent d2cef85187
commit f853cb73b5
32 changed files with 798 additions and 121 deletions
@@ -5,17 +5,12 @@ import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.annotation.Transient;
import org.springframework.data.domain.Persistable;
import org.springframework.data.relational.core.mapping.Column;
import java.time.LocalDateTime;
/**
* 数据库实体基类
*
* @author 张翔
* @date 2026-03-13
*/
public abstract class BaseEntity implements Persistable<Long> {
@Id
@@ -40,6 +35,9 @@ public abstract class BaseEntity implements Persistable<Long> {
@Column("deleted_at")
private LocalDateTime deletedAt;
@Transient
private boolean newEntity = true;
@Override
public Long getId() {
return id;
@@ -89,12 +87,16 @@ public abstract class BaseEntity implements Persistable<Long> {
this.deletedAt = deletedAt;
}
/**
* 判断实体是否为新的
* 如果createdAt为null,则认为是新实体
*/
@Override
public boolean isNew() {
return createdAt == null;
return newEntity;
}
public void markNotNew() {
this.newEntity = false;
}
public void markNew() {
this.newEntity = true;
}
}
@@ -7,6 +7,7 @@ import cn.novalon.gym.manage.db.dao.AuditLogDao;
import cn.novalon.gym.manage.db.entity.AuditLogEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -26,10 +27,12 @@ public class AuditLogRepository implements IAuditLogRepository {
private final AuditLogDao auditLogDao;
private final AuditLogConverter auditLogConverter;
private final R2dbcEntityTemplate r2dbcEntityTemplate;
public AuditLogRepository(AuditLogDao auditLogDao, AuditLogConverter auditLogConverter) {
public AuditLogRepository(AuditLogDao auditLogDao, AuditLogConverter auditLogConverter, R2dbcEntityTemplate r2dbcEntityTemplate) {
this.auditLogDao = auditLogDao;
this.auditLogConverter = auditLogConverter;
this.r2dbcEntityTemplate = r2dbcEntityTemplate;
}
@Override
@@ -41,6 +44,12 @@ public class AuditLogRepository implements IAuditLogRepository {
@Override
public Mono<AuditLog> save(AuditLog auditLog) {
AuditLogEntity entity = auditLogConverter.toEntity(auditLog);
if (entity.isNew()) {
return r2dbcEntityTemplate.insert(AuditLogEntity.class)
.using(entity)
.doOnNext(e -> e.markNotNew())
.map(auditLogConverter::toDomain);
}
return auditLogDao.save(entity)
.map(auditLogConverter::toDomain);
}
@@ -49,6 +49,12 @@ public class OperationLogRepository implements IOperationLogRepository {
@Override
public Mono<OperationLog> save(OperationLog operationLog) {
OperationLogEntity entity = operationLogConverter.toEntity(operationLog);
if (entity.isNew()) {
return r2dbcEntityTemplate.insert(OperationLogEntity.class)
.using(entity)
.doOnNext(e -> e.markNotNew())
.map(operationLogConverter::toDomain);
}
return operationLogDao.save(entity)
.map(operationLogConverter::toDomain);
}
@@ -60,6 +60,20 @@ public class SysMenuRepository implements ISysMenuRepository {
@Override
public Mono<SysMenu> save(SysMenu sysMenu) {
SysMenuEntity entity = sysMenuConverter.toEntity(sysMenu);
if (entity.isNew()) {
return r2dbcEntityTemplate.insert(SysMenuEntity.class)
.using(entity)
.doOnNext(e -> e.markNotNew())
.map(sysMenuConverter::toDomain);
}
return sysMenuDao.save(entity)
.map(sysMenuConverter::toDomain);
}
@Override
public Mono<SysMenu> update(SysMenu sysMenu) {
SysMenuEntity entity = sysMenuConverter.toEntity(sysMenu);
entity.markNotNew();
return sysMenuDao.save(entity)
.map(sysMenuConverter::toDomain);
}
@@ -4,7 +4,9 @@ import cn.novalon.gym.manage.sys.core.domain.SysPermission;
import cn.novalon.gym.manage.sys.core.repository.ISysPermissionRepository;
import cn.novalon.gym.manage.db.converter.SysPermissionConverter;
import cn.novalon.gym.manage.db.dao.SysPermissionDao;
import cn.novalon.gym.manage.db.entity.SysPermissionEntity;
import org.springframework.data.domain.Sort;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -20,10 +22,12 @@ public class SysPermissionRepository implements ISysPermissionRepository {
private final SysPermissionDao sysPermissionDao;
private final SysPermissionConverter sysPermissionConverter;
private final R2dbcEntityTemplate r2dbcEntityTemplate;
public SysPermissionRepository(SysPermissionDao sysPermissionDao, SysPermissionConverter sysPermissionConverter) {
public SysPermissionRepository(SysPermissionDao sysPermissionDao, SysPermissionConverter sysPermissionConverter, R2dbcEntityTemplate r2dbcEntityTemplate) {
this.sysPermissionDao = sysPermissionDao;
this.sysPermissionConverter = sysPermissionConverter;
this.r2dbcEntityTemplate = r2dbcEntityTemplate;
}
@Override
@@ -40,7 +44,14 @@ public class SysPermissionRepository implements ISysPermissionRepository {
@Override
public Mono<SysPermission> save(SysPermission sysPermission) {
return sysPermissionDao.save(sysPermissionConverter.toEntity(sysPermission))
SysPermissionEntity entity = sysPermissionConverter.toEntity(sysPermission);
if (entity.isNew()) {
return r2dbcEntityTemplate.insert(SysPermissionEntity.class)
.using(entity)
.doOnNext(e -> e.markNotNew())
.map(sysPermissionConverter::toDomain);
}
return sysPermissionDao.save(entity)
.map(sysPermissionConverter::toDomain);
}
@@ -4,6 +4,8 @@ import cn.novalon.gym.manage.sys.core.domain.SysRolePermission;
import cn.novalon.gym.manage.sys.core.repository.ISysRolePermissionRepository;
import cn.novalon.gym.manage.db.converter.SysRolePermissionConverter;
import cn.novalon.gym.manage.db.dao.SysRolePermissionDao;
import cn.novalon.gym.manage.db.entity.SysRolePermissionEntity;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -19,15 +21,24 @@ public class SysRolePermissionRepository implements ISysRolePermissionRepository
private final SysRolePermissionDao sysRolePermissionDao;
private final SysRolePermissionConverter sysRolePermissionConverter;
private final R2dbcEntityTemplate r2dbcEntityTemplate;
public SysRolePermissionRepository(SysRolePermissionDao sysRolePermissionDao, SysRolePermissionConverter sysRolePermissionConverter) {
public SysRolePermissionRepository(SysRolePermissionDao sysRolePermissionDao, SysRolePermissionConverter sysRolePermissionConverter, R2dbcEntityTemplate r2dbcEntityTemplate) {
this.sysRolePermissionDao = sysRolePermissionDao;
this.sysRolePermissionConverter = sysRolePermissionConverter;
this.r2dbcEntityTemplate = r2dbcEntityTemplate;
}
@Override
public Mono<SysRolePermission> save(SysRolePermission rolePermission) {
return sysRolePermissionDao.save(sysRolePermissionConverter.toEntity(rolePermission))
SysRolePermissionEntity entity = sysRolePermissionConverter.toEntity(rolePermission);
if (entity.isNew()) {
return r2dbcEntityTemplate.insert(SysRolePermissionEntity.class)
.using(entity)
.doOnNext(e -> e.markNotNew())
.map(sysRolePermissionConverter::toDomain);
}
return sysRolePermissionDao.save(entity)
.map(sysRolePermissionConverter::toDomain);
}
@@ -53,6 +53,12 @@ public class SysRoleRepository implements ISysRoleRepository {
@Override
public Mono<SysRole> save(SysRole sysRole) {
SysRoleEntity entity = sysRoleConverter.toEntity(sysRole);
if (entity.isNew()) {
return r2dbcEntityTemplate.insert(SysRoleEntity.class)
.using(entity)
.doOnNext(e -> e.markNotNew())
.map(sysRoleConverter::toDomain);
}
return sysRoleDao.save(entity)
.map(sysRoleConverter::toDomain);
}
@@ -156,6 +162,7 @@ public class SysRoleRepository implements ISysRoleRepository {
@Override
public Mono<SysRole> updateRole(SysRole role) {
SysRoleEntity entity = sysRoleConverter.toEntity(role);
entity.markNotNew();
return sysRoleDao.save(entity)
.map(sysRoleConverter::toDomain);
}
@@ -70,6 +70,20 @@ public class SysUserRepository implements ISysUserRepository {
@Override
public Mono<SysUser> save(SysUser sysUser) {
SysUserEntity entity = sysUserConverter.toEntity(sysUser);
if (entity.isNew()) {
return r2dbcEntityTemplate.insert(SysUserEntity.class)
.using(entity)
.doOnNext(e -> e.markNotNew())
.map(sysUserConverter::toDomain);
}
return sysUserDao.save(entity)
.map(sysUserConverter::toDomain);
}
@Override
public Mono<SysUser> update(SysUser sysUser) {
SysUserEntity entity = sysUserConverter.toEntity(sysUser);
entity.markNotNew();
return sysUserDao.save(entity)
.map(sysUserConverter::toDomain);
}
@@ -176,6 +190,7 @@ public class SysUserRepository implements ISysUserRepository {
public Mono<Void> logicalDeleteById(Long id) {
return sysUserDao.findById(id)
.flatMap(entity -> {
entity.markNotNew();
entity.setDeletedAt(java.time.LocalDateTime.now());
return sysUserDao.save(entity).then();
});
@@ -192,6 +207,7 @@ public class SysUserRepository implements ISysUserRepository {
public Mono<Void> restoreById(Long id) {
return sysUserDao.findById(id)
.flatMap(entity -> {
entity.markNotNew();
entity.setDeletedAt(null);
return sysUserDao.save(entity).then();
});