@Mapper
public interface UserConfigMapper extends BaseMapper<UserConfigEntity> {

}


/**
 * <p>
 * 用户配置信息(即系统用户的各类业务配置)
 * 每个用户一行记录,配置数据以json格式存储
 * </p>
 *
 * @author wandl
 * @since 2024-12-03
 */
@Getter
@Setter
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@TableName("sys_user_config")
public class UserConfigEntity extends AdminBaseEntity implements Serializable  {

    private static final long serialVersionUID = 1L;

    /**
     * 主键ID
     */
    @TableId(type = IdType.ASSIGN_ID)
    private Long id;

    /**
     * 应用ID,如:综合评价的应用ID
     */
    @TableField("app_id")
    private String appId;

    /**
     * 租户ID(即学校代码)
     */
    @TableField("tenant_id")
    private String tenantId;

    /**
     *  用户ID
     */
    @TableField("user_id")
    private Long userId;

    /**
     * 配置项名称,如:AppKey
     */
    @TableField("config_key")
    private String configKey;

    /**
     * 配置项数据分类:key-value、json-object、json-array
     */
    @TableField("config_data_type")
    private ConfigDataType configDataType;

    /**
     * 配置项值,如:xxxxx12645645
     */
    @TableField("config_value")
    private String configValue;

    public UserConfigVO toVO() {
        return new UserConfigVO()
                .setId(this.id)
                .setConfigKey(this.configKey)
                .setConfigDataType(this.configDataType)
                .setConfigValue(this.configValue)
                .setCreateTime(this.getCreateTime())
                .setUpdateTime(this.getUpdateTime());
    }

}

/**
 * <p>
 * 用户配置信息(即系统用户的各类业务配置)
 * 每个用户一行记录,配置数据以json格式存储
 * </p>
 *
 * @author wandl
 * @since 2024-12-03
 */
@ApiModel(value = "UserConfigVO", description = "用户配置信息(即系统用户的各类业务配置)VO")
@Getter
@Setter
@Accessors(chain = true)
public class UserConfigVO implements Serializable  {

    private static final long serialVersionUID = 1L;

    /**
     * 主键ID
     */
    @ApiModelProperty(value = "主键ID")
    @JsonSerialize(using = ToStringSerializer.class)
    private Long id;

    /**
     * 配置项名称,如:AppKey
     */
    @ApiModelProperty(value = "配置项名称,如:AppKey")
    private String configKey;

    /**
     * 配置项数据分类:key-value、json-object、json-array
     */
    @ApiModelProperty(value = "配置项数据分类:key-value、json-object、json-array")
    private ConfigDataType configDataType;

    /**
     * 配置项值,如:12645645
     */
    @ApiModelProperty(value = "配置项值,如:12645645")
    private String configValue;

    /**
     * 创建时间
     */
    @ApiModelProperty(value = "创建时间")
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    @JsonSerialize(using = LocalDateTimeSerializer.class)
    private LocalDateTime createTime;

    /**
     * 修改时间
     */
    @ApiModelProperty(value = "修改时间")
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    @JsonSerialize(using = LocalDateTimeSerializer.class)
    private LocalDateTime updateTime;

}


import java.util.List;
import java.util.Map;

/**
 * 用户配置服务
 */
public interface IUserConfigService extends IService<UserConfigEntity> {

    /**
     * 保存用户配置
     * @param configAddParam 用户配置
     * @return 是否保存成功
     */
    boolean saveUserConfig(UserConfigAddParam configAddParam);

    /**
     * 保存用户配置(批量)
     * @param configSetAddParam 用户配置
     * @return 是否保存成功
     */
    boolean saveUserConfig(UserConfigSetAddParam configSetAddParam);

    /**
     * 删除用户配置
     * @param appId 应用id
     * @param configKeys 配置key
     * @param tenantId 租户id
     * @param userId 用户id
     * @return 是否删除成功
     */
    boolean deleteUserConfig(String appId, String tenantId, Long userId, String ... configKeys);

    /**
     * 更新用户配置
     * @param configUpdateParam 用户配置
     * @return 是否更新成功
     */
    boolean updateUserConfig(UserConfigUpdateParam configUpdateParam);

    /**
     * 更新用户配置(批量)
     * @param configSetUpdateParam 用户配置
     * @return 是否更新成功
     */
    boolean updateUserConfig(UserConfigSetUpdateParam configSetUpdateParam);

    /**
     * 根据用户id查询用户配置
     * @param appId 应用id
     * @param tenantId 租户id
     * @param userId 用户id
     * @return 用户配置列表
     */
    Map<String, UserConfigVO> getUserConfigMap(String appId, String tenantId, Long userId);

    /**
     * 根据用户id查询用户配置
     * @param appId 应用id
     * @param tenantId 租户id
     * @param userId 用户id
     * @return 用户配置列表
     */
    List<UserConfigVO> getUserConfigList(String appId, String tenantId, Long userId);

    /**
     * 根据用户id查询用户配置
     * @param appId 应用id
     * @param tenantId 租户id
     * @param userId 用户id
     * @param configKey 配置key
     * @return 用户配置
     */
    UserConfigVO getUserConfig(String appId, String tenantId, Long userId, String configKey);

}

@Service
@RequiredArgsConstructor
@Slf4j
public class UserConfigServiceImpl extends ServiceImpl<UserConfigMapper, UserConfigEntity> implements IUserConfigService {

    public final RedisOperationTemplate redisOperationTemplate;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveUserConfig(UserConfigAddParam configAddParam) {
        // 1、根据AppId、TenantId、UserId、ConfigKey查询数据
        UserConfigEntity oldEntity= getBaseMapper().selectOne(new LambdaQueryWrapper<UserConfigEntity>()
                .eq(UserConfigEntity::getAppId, configAddParam.getAppId())
                .eq(UserConfigEntity::getTenantId, configAddParam.getTenantId())
                .eq(UserConfigEntity::getUserId, SubjectUtils.getUserIdLong())
                .eq(UserConfigEntity::getConfigKey, configAddParam.getConfigKey()));
        // 2、如果存在则更新
        if (Objects.nonNull(oldEntity)){
            oldEntity.setConfigDataType(configAddParam.getConfigDataType())
                     .setConfigValue(configAddParam.getConfigValue());
            return this.updateById(oldEntity);
        }
        // 3、不存在则新增
        UserConfigEntity entity =  new UserConfigEntity()
                .setAppId(configAddParam.getAppId())
                .setTenantId(configAddParam.getTenantId())
                .setUserId(SubjectUtils.getUserIdLong())
                .setConfigKey(configAddParam.getConfigKey())
                .setConfigDataType(configAddParam.getConfigDataType())
                .setConfigValue(configAddParam.getConfigValue());
        return this.save(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveUserConfig(UserConfigSetAddParam configSetAddParam) {
        // 1、进行参数校验
        if(Objects.isNull(configSetAddParam) || CollectionUtils.isEmpty(configSetAddParam.getParamList())){
            log.warn("参数为空, configSetAddParam: {}", configSetAddParam);
            return Boolean.FALSE;
        }
        // 2、查询当前操作租户的所有配置
        Optional<UserConfigAddParam> firstParam = configSetAddParam.getParamList().stream().filter(Objects::nonNull).findFirst();
        if (!firstParam.isPresent()) {
            log.warn("参数为空, configSetAddParam: {}", configSetAddParam);
            return Boolean.FALSE;
        }
        List<UserConfigEntity> newEntityList = Lists.newArrayList();
        List<UserConfigEntity> updateEntityList = Lists.newArrayList();
        // 3、查询到当前操作租户的所有配置
        List<UserConfigEntity> oldEntityList = getBaseMapper().selectList(new LambdaQueryWrapper<UserConfigEntity>()
                .eq(UserConfigEntity::getAppId, firstParam.get().getAppId())
                .eq(UserConfigEntity::getTenantId, firstParam.get().getTenantId()));
        if(CollectionUtils.isEmpty(oldEntityList)){
            for (UserConfigAddParam configAddParam : configSetAddParam.getParamList()) {
                newEntityList.add(new UserConfigEntity()
                        .setAppId(configAddParam.getAppId())
                        .setTenantId(configAddParam.getTenantId())
                        .setConfigKey(configAddParam.getConfigKey())
                        .setConfigDataType(configAddParam.getConfigDataType())
                        .setConfigValue(configAddParam.getConfigValue()));
            }
        } else {
            // 根据ConfigKey转换成Map
            Map<String, UserConfigEntity> oldEntityMap = oldEntityList.stream().collect(Collectors.toMap(UserConfigEntity::getConfigKey, entity -> entity, (a, b) -> a));
            // 遍历新增数据
            for (UserConfigAddParam configAddParam : configSetAddParam.getParamList()) {
                // 如果不存在则新增
                buildEntity(newEntityList, updateEntityList, oldEntityMap, configAddParam);
            }
        }
        if (!CollectionUtils.isEmpty(newEntityList)){
            this.saveBatch(newEntityList);
        }
        if (!CollectionUtils.isEmpty(updateEntityList)){
            this.updateBatchById(updateEntityList);
        }
        return Boolean.TRUE;
    }

    private void buildEntity(List<UserConfigEntity> newEntityList, List<UserConfigEntity> updateEntityList, Map<String, UserConfigEntity> oldEntityMap, UserConfigAddParam configAddParam) {
        UserConfigEntity oldEntity = oldEntityMap.get(configAddParam.getConfigKey());
        if (Objects.isNull(oldEntity)) {
            newEntityList.add(new UserConfigEntity()
                    .setAppId(configAddParam.getAppId())
                    .setTenantId(configAddParam.getTenantId())
                    .setConfigKey(configAddParam.getConfigKey())
                    .setConfigDataType(configAddParam.getConfigDataType())
                    .setConfigValue(configAddParam.getConfigValue()));
        } else {
            // 如果存在则更新
            oldEntity.setConfigDataType(configAddParam.getConfigDataType())
                    .setConfigValue(configAddParam.getConfigValue());
            updateEntityList.add(oldEntity);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteUserConfig(String appId, String tenantId, Long userId, String... configKeys) {
        // 1、进行参数校验
        if(Objects.isNull(appId) || ArrayUtils.isEmpty(configKeys)){
            return Boolean.FALSE;
        }
        // 2、删除数据
        boolean rt = SqlHelper.retBool(getBaseMapper().delete(new LambdaQueryWrapper<UserConfigEntity>()
                .eq(UserConfigEntity::getAppId, appId)
                .eq(UserConfigEntity::getTenantId, tenantId)
                .eq(UserConfigEntity::getUserId, userId)
                .eq(configKeys.length == 1, UserConfigEntity::getConfigKey, configKeys[0])
                .in(configKeys.length > 1, UserConfigEntity::getConfigKey, Arrays.asList(configKeys))));
        // 3、删除成功则删除缓存
        if (rt){
            String rdsKey = BizRedisKey.USER_CONFIG.getKey(appId + StringPool.DASH + tenantId, userId);
            redisOperationTemplate.hDel(rdsKey, configKeys);
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUserConfig(UserConfigUpdateParam configUpdateParam) {
        // 1、根据ID查询数据,如果不存在则返回
        UserConfigEntity entity = getBaseMapper().selectById(configUpdateParam.getId());
        if (Objects.isNull(entity)){
            return Boolean.FALSE;
        }
        // 2、更新数据
        entity.setConfigKey(configUpdateParam.getConfigKey())
                .setConfigDataType(configUpdateParam.getConfigDataType())
                .setConfigValue(configUpdateParam.getConfigValue());
        return this.updateById(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUserConfig(UserConfigSetUpdateParam configSetUpdateParam) {
        // 1、进行参数校验
        if(Objects.isNull(configSetUpdateParam) || (CollectionUtils.isEmpty(configSetUpdateParam.getAddList())
                && CollectionUtils.isEmpty(configSetUpdateParam.getUpdateList()))){
            return Boolean.FALSE;
        }
        // 2、有新增数据的时候,先处理新增数据
        List<UserConfigEntity> newEntityList = Lists.newArrayList();
        List<UserConfigEntity> updateEntityList = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(configSetUpdateParam.getAddList())){
            // 2.1、第一个元素的AppId、TenantId查询当前操作用户的所有配置
            Optional<UserConfigAddParam> firstParam = configSetUpdateParam.getAddList().stream().filter(Objects::nonNull).findFirst();
            if (firstParam.isPresent()) {
                // 2.1.1、查询到当前操作用户的所有配置
                List<UserConfigEntity> oldEntityList = getBaseMapper().selectList(new LambdaQueryWrapper<UserConfigEntity>()
                        .eq(UserConfigEntity::getAppId, firstParam.get().getAppId())
                        .eq(UserConfigEntity::getTenantId, firstParam.get().getTenantId())
                        .eq(UserConfigEntity::getUserId, SubjectUtils.getUserIdLong()));
                // 2.1.2、如果查询到当前操作用户的所有配置,则需要判断新增数据是否已经存在
                if (!CollectionUtils.isEmpty(oldEntityList)) {
                    // 根据ConfigKey转换成Map
                    Map<String, UserConfigEntity> oldEntityMap = oldEntityList.stream().collect(Collectors.toMap(UserConfigEntity::getConfigKey, entity -> entity, (a, b) -> a));
                    // 遍历新增数据
                    for (UserConfigAddParam configAddParam : configSetUpdateParam.getAddList()) {
                        buildEntity(newEntityList, updateEntityList, oldEntityMap, configAddParam);
                    }
                }
            }
            for (UserConfigAddParam configAddParam: configSetUpdateParam.getAddList()){
                newEntityList.add(new UserConfigEntity()
                        .setAppId(configAddParam.getAppId())
                        .setTenantId(configAddParam.getTenantId())
                        .setUserId(SubjectUtils.getUserIdLong())
                        .setConfigKey(configAddParam.getConfigKey())
                        .setConfigDataType(configAddParam.getConfigDataType())
                        .setConfigValue(configAddParam.getConfigValue()));
            }
            this.saveBatch(newEntityList);
        }
        // 3、有更新数据的时候
        if (!CollectionUtils.isEmpty(configSetUpdateParam.getUpdateList())){
            // 3.1、第一个元素的AppId、TenantId查询当前操作用户的所有配置
            Set<Long> idSet = configSetUpdateParam.getUpdateList().stream().filter(Objects::nonNull).map(UserConfigUpdateParam::getId).collect(Collectors.toSet());
            if (!CollectionUtils.isEmpty(idSet)){
                List<UserConfigEntity> oldEntityList = getBaseMapper().selectBatchIds(idSet);
                // 3.2、如果有数据则进行更新
                if (!CollectionUtils.isEmpty(oldEntityList)){
                    // 3.2.1、转换成Map
                    Map<Long, UserConfigEntity> oldEntityMap = oldEntityList.stream().collect(Collectors.toMap(UserConfigEntity::getId, entity -> entity, (a, b) -> a));
                    // 3.2.2、遍历更新数据
                    for (UserConfigUpdateParam configUpdateParam: configSetUpdateParam.getUpdateList()){
                        // 3.2.2.1、跳过空数据
                        if(Objects.isNull(configUpdateParam)){
                            continue;
                        }
                        // 3.2.2.2、根据ConfigKey查询数据,如果没有则跳过
                        UserConfigEntity oldEntity = oldEntityMap.get(configUpdateParam.getId());
                        if (Objects.isNull(oldEntity)){
                            continue;
                        }
                        // 3.2.2.3、 覆盖数据
                        oldEntity.setConfigDataType(configUpdateParam.getConfigDataType())
                                .setConfigValue(configUpdateParam.getConfigValue());
                        updateEntityList.add(oldEntity);
                    }
                }
            }
            // 3.3、更新数据
            if (!CollectionUtils.isEmpty(updateEntityList)){
                this.updateBatchById(updateEntityList);
            }
        }
        return Boolean.TRUE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(UserConfigEntity entity) {
        // 1、保存数据
        boolean rt = super.save(entity);
        // 2、保存成功则存入缓存
        if (rt){
            String rdsKey = BizRedisKey.TENANT_CONFIG.getKey(entity.getAppId() + StringPool.DASH + entity.getTenantId(), entity.getUserId());
            redisOperationTemplate.hSet(rdsKey, entity.getConfigKey(), entity.toVO());
        }
        return rt;
    }

    @Override
    public boolean saveOrUpdate(UserConfigEntity entity) {
        // 1、保存/更新数据
        boolean rt = super.saveOrUpdate(entity);
        // 2、保存成功则存入缓存
        if (rt){
            String rdsKey = BizRedisKey.TENANT_CONFIG.getKey(entity.getAppId() + StringPool.DASH + entity.getTenantId(), entity.getUserId());
            redisOperationTemplate.hSet(rdsKey, entity.getConfigKey(), entity.toVO());
        }
        return rt;
    }

    @Override
    public boolean saveOrUpdateBatch(Collection<UserConfigEntity> entityList) {
        throw new UnsupportedOperationException("不支持的方法!");
    }

    /**
     * 批量插入
     *
     * @param entityList ignore
     * @param batchSize  ignore
     * @return ignore
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveBatch(Collection<UserConfigEntity> entityList, int batchSize) {
        String sqlStatement = getSqlStatement(SqlMethod.INSERT_ONE);
        return executeBatch(entityList, batchSize, (sqlSession, entity) -> {
            int rt = sqlSession.insert(sqlStatement, entity);
            if(rt > 0){
                // 3.2、保存成功则存入缓存
                String rdsKey = BizRedisKey.TENANT_CONFIG.getKey(entity.getAppId() + StringPool.DASH + entity.getTenantId(), entity.getUserId());
                redisOperationTemplate.hSet(rdsKey, entity.getConfigKey(), entity.toVO());
            }
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateBatchById(Collection<UserConfigEntity> entityList) {
        String sqlStatement = getSqlStatement(SqlMethod.UPDATE_BY_ID);
        return executeBatch(entityList, DEFAULT_BATCH_SIZE, (sqlSession, entity) -> {
            MapperMethod.ParamMap<UserConfigEntity> param = new MapperMethod.ParamMap<>();
            param.put(Constants.ENTITY, entity);
            int rt = sqlSession.update(sqlStatement, param);
            if(rt > 0){
                // 3.2、保存成功则存入缓存
                String rdsKey = BizRedisKey.TENANT_CONFIG.getKey(entity.getAppId() + StringPool.DASH + entity.getTenantId(), entity.getUserId());
                redisOperationTemplate.hSet(rdsKey, entity.getConfigKey(), entity.toVO());
            }
        });
    }

    @Override
    public boolean updateById(UserConfigEntity entity) {
        boolean rt = super.updateById(entity);
        // 3.2、保存成功则存入缓存
        if (rt){
            String rdsKey = BizRedisKey.TENANT_CONFIG.getKey(entity.getAppId() + StringPool.DASH + entity.getTenantId(), entity.getUserId());
            redisOperationTemplate.hSet(rdsKey, entity.getConfigKey(), entity.toVO());
        }
        return rt;
    }

    @Override
    public Map<String, UserConfigVO> getUserConfigMap(String appId, String tenantId, Long userId) {
        if (Objects.isNull(appId) || !StringUtils.hasText(tenantId) || Objects.isNull(userId)) {
            return Collections.emptyMap();
        }
        // 1、优先获取缓存中的数据
        String rdsKey = BizRedisKey.USER_CONFIG.getKey(appId + StringPool.DASH + tenantId, userId);
        Map<String, UserConfigVO> configMap = redisOperationTemplate.hmGetFor(rdsKey, String::valueOf, UserConfigVO.class);
        // 2、如果缓存中有数据则直接返回
        if (!CollectionUtils.isEmpty(configMap)) {
            return configMap;
        } else {
            // 3、缓存中没有数据则查询数据库
            List<UserConfigEntity> userConfigList = getBaseMapper().selectList(new LambdaQueryWrapper<UserConfigEntity>()
                    .eq(UserConfigEntity::getDeleted, 0)
                    .eq(UserConfigEntity::getAppId, appId)
                    .eq(UserConfigEntity::getTenantId, tenantId)
                    .eq(UserConfigEntity::getUserId, userId));
            if (CollectionUtils.isEmpty(userConfigList)) {
                return Collections.emptyMap();
            }
            // 4、将数据转换成map
            configMap = userConfigList.stream().collect(Collectors.toMap(UserConfigEntity::getConfigKey, UserConfigEntity::toVO, (k1, k2) -> k1));
            // 4、将数据存入缓存
            redisOperationTemplate.hmSet(rdsKey, configMap);
            return configMap;
        }
    }

    @Override
    public List<UserConfigVO> getUserConfigList(String appId, String tenantId, Long userId) {
        // 1、获取配置信息
        Map<String, UserConfigVO> configMap = getUserConfigMap(appId , tenantId, userId);
        if (CollectionUtils.isEmpty(configMap)) {
            return Collections.emptyList();
        }
        // 2、返回配置信息
        return new ArrayList<>(configMap.values());
    }

    @Override
    public UserConfigVO getUserConfig(String appId, String tenantId, Long userId, String configKey) {
        // 1、获取配置信息
        Map<String, UserConfigVO> configMap = getUserConfigMap(appId , tenantId, userId);
        if (CollectionUtils.isEmpty(configMap)) {
            return null;
        }
        // 2、返回配置信息
        return configMap.get(configKey);
    }

}
作者:Jeebiz  创建时间:2025-04-13 16:12
最后编辑:Jeebiz  更新时间:2025-04-13 16:32