refactor(app-user): 移除跨库JOIN依赖,改用冗余字段存储用户信息

- 在AppUser实体中新增nickname和phone冗余字段
- 移除AppUserMapper.xml中的跨库JOIN查询gxwebsoft_core.sys_user表
- 更新搜索条件使用本地冗余字段而非关联表字段
- 注入UserService用于写入冗余用户基础信息
- 邀请成员时查询系统用户信息并冗余存储到本地表
- 日志输出中增加用户名信息便于调试追踪
This commit is contained in:
2026-03-29 01:19:48 +08:00
parent 6aeface82d
commit 75c13bada8
3 changed files with 29 additions and 8 deletions

View File

@@ -35,9 +35,15 @@ public class AppUser implements Serializable {
@Schema(description = "用户名(冗余)") @Schema(description = "用户名(冗余)")
private String username; private String username;
@Schema(description = "昵称(冗余)")
private String nickname;
@Schema(description = "头像(冗余)") @Schema(description = "头像(冗余)")
private String avatar; private String avatar;
@Schema(description = "手机号(冗余,脱敏存储)")
private String phone;
@Schema(description = "角色: owner/admin/developer/viewer") @Schema(description = "角色: owner/admin/developer/viewer")
private String role; private String role;

View File

@@ -2,13 +2,11 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gxwebsoft.app.mapper.AppUserMapper"> <mapper namespace="com.gxwebsoft.app.mapper.AppUserMapper">
<!-- 关联查询sql --> <!-- 关联查询sql(已移除跨库 JOIN gxwebsoft_core.sys_user用户信息从冗余字段读取 -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.*, w.website_name, w.website_code, w.website_icon, SELECT a.*, w.website_name, w.website_code, w.website_icon
u.nickname, u.avatar AS user_avatar, u.phone
FROM app_user a FROM app_user a
LEFT JOIN cms_website w ON a.website_id = w.website_id AND w.deleted = 0 LEFT JOIN cms_website w ON a.website_id = w.website_id AND w.deleted = 0
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
@@ -21,7 +19,7 @@
</if> </if>
<if test="param.username != null and param.username != ''"> <if test="param.username != null and param.username != ''">
AND (a.username LIKE CONCAT('%', #{param.username}, '%') AND (a.username LIKE CONCAT('%', #{param.username}, '%')
OR u.nickname LIKE CONCAT('%', #{param.username}, '%')) OR a.nickname LIKE CONCAT('%', #{param.username}, '%'))
</if> </if>
<if test="param.role != null and param.role != ''"> <if test="param.role != null and param.role != ''">
AND a.role = #{param.role} AND a.role = #{param.role}
@@ -46,8 +44,7 @@
</if> </if>
<if test="param.keywords != null and param.keywords != ''"> <if test="param.keywords != null and param.keywords != ''">
AND (a.username LIKE CONCAT('%', #{param.keywords}, '%') AND (a.username LIKE CONCAT('%', #{param.keywords}, '%')
OR u.nickname LIKE CONCAT('%', #{param.keywords}, '%') OR a.nickname LIKE CONCAT('%', #{param.keywords}, '%'))
)
</if> </if>
</where> </where>
</sql> </sql>

View File

@@ -10,9 +10,12 @@ import com.gxwebsoft.app.entity.AppUser;
import com.gxwebsoft.app.param.AppUserParam; import com.gxwebsoft.app.param.AppUserParam;
import com.gxwebsoft.common.core.web.PageParam; import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.service.UserService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
@@ -26,6 +29,10 @@ import java.util.List;
@Service @Service
public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> implements AppUserService { public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> implements AppUserService {
/** 注入同 jar 包内的 UserService用于写入冗余用户信息不做跨库 JOIN */
@Resource
private UserService userService;
@Override @Override
public PageResult<AppUser> pageRel(AppUserParam param) { public PageResult<AppUser> pageRel(AppUserParam param) {
PageParam<AppUser, AppUserParam> page = new PageParam<>(param); PageParam<AppUser, AppUserParam> page = new PageParam<>(param);
@@ -56,6 +63,12 @@ public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> impl
throw new RuntimeException("该用户已经是应用成员"); throw new RuntimeException("该用户已经是应用成员");
} }
// 查询用户基础信息并冗余写入,避免跨库 JOIN
User sysUser = userService.getByIdIgnoreTenant(userId);
if (sysUser == null) {
throw new RuntimeException("用户不存在userId=" + userId);
}
AppUser appUser = new AppUser(); AppUser appUser = new AppUser();
appUser.setWebsiteId(websiteId); appUser.setWebsiteId(websiteId);
appUser.setUserId(userId); appUser.setUserId(userId);
@@ -64,9 +77,14 @@ public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> impl
appUser.setInviteTime(LocalDateTime.now()); appUser.setInviteTime(LocalDateTime.now());
appUser.setStatus(0); appUser.setStatus(0);
appUser.setSortNumber(0); appUser.setSortNumber(0);
// 冗余写入用户基础信息,彻底解除跨库 JOIN 依赖
appUser.setUsername(sysUser.getUsername());
appUser.setNickname(sysUser.getNickname());
appUser.setAvatar(sysUser.getAvatar());
appUser.setPhone(sysUser.getPhone());
save(appUser); save(appUser);
log.info("邀请成员成功websiteId={}, userId={}, role={}", websiteId, userId, role); log.info("邀请成员成功websiteId={}, userId={}, username={}, role={}", websiteId, userId, sysUser.getUsername(), role);
return appUser; return appUser;
} }