建立字典库_alibaba inc「建议收藏」

建立字典库_alibaba inc「建议收藏」终于结束从零搭建springcloud的部分了,目前也仅仅是学习了最最基本的逻辑,同时包含了开发系统的一些基本的逻辑

PigUserDetailsService  代码地址与接口文档看总目录:【学习笔记】记录冷冷-pig项目的学习过程,大概包括Authorization Server、springcloud、Mybatis Plus~~~_清晨敲代码的博客-CSDN博客


终于结束从零搭建springcloud的部分了,目前也仅仅是学习了最最基本的逻辑,同时包含了开发系统的一些基本的逻辑。接下来就按照 pig 文档将其余基本的内容再熟悉一下,看一遍和写一遍真的不一样呐~~~

那接下来就一小模块一小模块的学习啦,加油吧少年!

本文及以后的文章还是基于前面的No6系列文章开发的,可以看之前文章顶部的内容总结,简单了解详情~

目录

A1.添加字典功能

B1.步骤

B2.编码

B3.测试

遇到的问题:

1.基础增删改查需要判断是否存在

2.增删改查业务添加一个同意逻辑处理模块


A1.添加字典功能

字典,又分为字典和字典项,每个字典项属于某一个字典,每个字典有多个字典项。这样前端就可以根据字典拿到字典项。

获取到的字典的属性,要尽可能适用于前端的组件,方便前端使用。

B1.步骤

首先,我们需要提供一个字典的增删改查功能,然后再提供一个字典项的增删改查功能,同时字典项必须要关联一个字典,并且字典项要有值和标签,值对应业务操作,标签对应用户展示。

建立字典库_alibaba inc「建议收藏」

 由于没有复杂业务,所以不需要关联表操作,不需要写 mapper 语句~

B2.编码

确定好数据结构之后,一定要先写接口文档,梳理编码逻辑!

1.新建两个数据表,一个字典sys_dict,一个字典项sys_dict_item,设置 id 自增;

2.新建表对应的实体类,要设置 mps 的id自增,和逻辑删除注解;

3.新建 mapper 接口,继承 mps 的 BaseMapper ,不需要新增方法;

4.新建 service 接口及实现类,继承 mps 的 IService、IServiceImpl ;

5.新建 controller 类,编写接口端点方法,并确定好需要调用的 service 方法;

【我习惯了解数据接口和接口文档后,就针对他们编写 controller 中的接口端点,然后再编写 service 业务方法】

6.有些复杂的业务需要增加业务方法,所以修改 service 类,编写 controller 需要的方法;

-- 1.新建两个数据表,一个字典sys_dict,一个字典项sys_dict_item,设置 id 自增;

CREATE TABLE `sys_dict` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `dict_type` varchar(100) DEFAULT NULL COMMENT '标识',
  `description` varchar(100) DEFAULT NULL COMMENT '描述',
  `remark` varchar(255) DEFAULT NULL COMMENT '备注',
  `system_flag` char(1) DEFAULT '0' COMMENT '是否是系统内置',
  `del_flag` char(1) DEFAULT '0' COMMENT '删除标记',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
  `update_by` varchar(64) DEFAULT NULL COMMENT '更新人',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `sys_dict_del_flag` (`del_flag`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COMMENT='字典表'

CREATE TABLE `sys_dict_item` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `dict_id` bigint(20) NOT NULL COMMENT '字典ID',
  `dict_type` varchar(100) DEFAULT NULL COMMENT '字典标识',
  `value` varchar(100) DEFAULT NULL COMMENT '值',
  `label` varchar(100) DEFAULT NULL COMMENT '标签',
  `description` varchar(100) DEFAULT NULL COMMENT '描述',
  `sort_order` int(11) NOT NULL DEFAULT '0' COMMENT '排序(升序)',
  `remark` varchar(255) DEFAULT ' ' COMMENT '备注',
  `del_flag` char(1) DEFAULT '0' COMMENT '删除标记',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
  `update_by` varchar(64) DEFAULT NULL COMMENT '修改人',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `sys_dict_value` (`value`) USING BTREE,
  KEY `sys_dict_label` (`label`) USING BTREE,
  KEY `sys_dict_del_flag` (`del_flag`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb4 COMMENT='字典项'
//2.新建表对应的实体类,要设置 mps 的id自增,和逻辑删除注解;

//新增
com.pig4cloud.pig.admin.api.entity.SysDict extends BaseEntity
com.pig4cloud.pig.admin.api.entity.SysDictItem extends BaseEntity
//3.新建 mapper 接口,继承 mps 的 BaseMapper ,不需要新增方法;

@Mapper
public interface SysDictMapper extends BaseMapper<SysDict> {
}

@Mapper
public interface SysDictItemMapper extends BaseMapper<SysDictItem> {
}
//4.新建 service 接口及实现类,继承 mps 的 IService、IServiceImpl ;

public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> implements SysDictService {
}

public class SysDictItemServiceImpl extends ServiceImpl<SysDictItemMapper, SysDictItem> implements SysDictItemService {
}
//5.新建 controller 类,编写接口端点方法,并确定好需要调用的 service 方法;

//其中只有两个更新和两个删除的需要重写对应的 service 方法,因为需要判断是否能删除,并且涉及到关联删除~
//其余的使用 mps 提供的 service 方法就行

@RestController
@RequestMapping("/dict")
@RequiredArgsConstructor
public class DictController {

    private final SysDictService sysDictService;

    private final SysDictItemService sysDictItemService;

    /**
     * @Description: 添加
     * @param: [dict]
     * @return: com.pig4cloud.pig.common.core.util.R<java.lang.Boolean>
     **/
    @SysLog("添加字典")
    @PostMapping
    @PreAuthorize("@pms.hasPermission('sys_dict_add')")
    public R<Boolean> save(@RequestBody SysDict dict) {

        //标签必须唯一,先判断是否已存在
        SysDict sysDict = sysDictService.getOne(Wrappers.<SysDict>lambdaQuery().eq(SysDict::getDictType, dict.getDictType()));
        if ( sysDict != null){
            return R.failed("标签已存在");
        }

        return R.ok(sysDictService.save(dict));
    }


    /**
     * @Description: 分页查询字典
     * @param: [page, dict]
     * @return: com.pig4cloud.pig.common.core.util.R<com.baomidou.mybatisplus.core.metadata.IPage<com.pig4cloud.pig.admin.api.entity.SysDict>>
     **/
    @SysLog("分页查询字典")
    @GetMapping("/page")
    @PreAuthorize("@pms.hasPermission('sys_dict_list')")
    public R<IPage<SysDict>> getPage(Page page, SysDict dict) {

        LambdaQueryWrapper<SysDict> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(SysDict::getDelFlag, CommonConstants.NOT_DELETE);

        if(StrUtil.isNotBlank(dict.getDictType())){
            wrapper.like(SysDict::getDictType, dict.getDictType());
        }
        if(StrUtil.isNotBlank(dict.getDictType())){
            wrapper.like(SysDict::getSystemFlag, dict.getSystemFlag());
        }

        return R.ok(sysDictService.page(page, wrapper));
    }

    /**
     * @Description: 通过ID查询字典
     * @param: [id]
     * @return: com.pig4cloud.pig.common.core.util.R<com.pig4cloud.pig.admin.api.entity.SysDict>
     **/
    @SysLog("通过ID查询字典")
    @GetMapping("/{id}")
    public R<SysDict> getById(@PathVariable Long id) {
        return R.ok(sysDictService.getById(id));
    }

    /**
     * @Description: 添加
     * @param: [dictItem]
     * @return: com.pig4cloud.pig.common.core.util.R<java.lang.Boolean>
     **/
    @SysLog("添加字典项")
    @PostMapping("/item")
    public R<Boolean> save(@RequestBody SysDictItem dictItem) {

        //value 必须唯一,先判断当前字典中是否已存在该 value
        SysDictItem sysDictItem = sysDictItemService.getOne(
                Wrappers.<SysDictItem>lambdaQuery().eq(SysDictItem::getDictType, dictItem.getDictType()).eq(SysDictItem::getValue, dictItem.getValue()));
        if ( sysDictItem != null){
            return R.failed("值已存在");
        }

        return R.ok(sysDictItemService.save(dictItem));
    }


    /**
     * @Description: 分页查询某个字典的字典项
     * @param: [page, dictItem]
     * @return: com.pig4cloud.pig.common.core.util.R<com.baomidou.mybatisplus.core.metadata.IPage<com.pig4cloud.pig.admin.api.entity.SysDictItem>>
     **/
    @SysLog("分页查询某个字典的字典项")
    @GetMapping("/item/page")
    @PreAuthorize("@pms.hasPermission('sys_dictItem_list')")
    public R<IPage<SysDictItem>> getDictItemPage(Page page, SysDictItem dictItem) {
        return R.ok(sysDictItemService.page(page,
                Wrappers.<SysDictItem>lambdaQuery().eq(SysDictItem::getDictType, dictItem.getDictType())
                        .eq(SysDictItem::getDelFlag, CommonConstants.NOT_DELETE)));
    }

    /**
     * @Description: 通过ID查询字典项
     * @param: [id]
     * @return: com.pig4cloud.pig.common.core.util.R<com.pig4cloud.pig.admin.api.entity.SysDictItem>
     **/
    @SysLog("通过ID查询字典项")
    @GetMapping("/item/{id}")
    public R<SysDictItem> getDictItemById(@PathVariable Long id) {
        return R.ok(sysDictItemService.getById(id));
    }

    /**
     * @Description: 通过字典标识查找字典项
     * @param: [type]
     * @return: com.pig4cloud.pig.common.core.util.R<java.util.List<com.pig4cloud.pig.admin.api.entity.SysDictItem>>
     **/
    @GetMapping("/dictType/{dictType}")
    public R<List<SysDictItem>> getDictByType(@PathVariable String dictType) {
        return R.ok(sysDictItemService.list(
                Wrappers.<SysDictItem>query().lambda().eq(SysDictItem::getDictType, dictType).eq(SysDictItem::getDelFlag, CommonConstants.NOT_DELETE)));
    }
}
//6.有些复杂的业务需要增加业务方法,所以修改 service 类,编写 controller 需要的方法;

@Service
@RequiredArgsConstructor
public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> implements SysDictService {

    private final SysDictItemMapper dictItemMapper;


    @Override
    public Boolean updateDict(SysDict sysDict) {
        //1.先拿到对应的存储的信息
        SysDict dict = this.getById(sysDict.getId());

        // 判断是不是系统内置的,如果是则抛异常不能修改
        if(!DictTypeEnum.SYSTEM.getType().equals(dict.getSystemFlag())){
            throw new RuntimeException("系统内置字典不能修改");
        }

        //不是系统内置,则进行修改
        this.updateById(sysDict);

        return Boolean.TRUE;
    }

    @Override
    public Boolean deleteDict(Long id) {
        //先拿到对应的存储的信息
        SysDict dict = this.getById(id);
        // 判断是不是系统内置的,如果是则抛异常不能删除
        if(!DictTypeEnum.SYSTEM.getType().equals(dict.getSystemFlag())){
            throw new RuntimeException("系统内置字典不允许删除");
        }
        //不是系统内置,则进行修改
        baseMapper.deleteById(id);
        //同时删除字典项
        dictItemMapper.delete(Wrappers.<SysDictItem>lambdaQuery().eq(SysDictItem::getDictId, id));

        return Boolean.TRUE;
    }


}

@Service
@RequiredArgsConstructor
public class SysDictItemServiceImpl extends ServiceImpl<SysDictItemMapper, SysDictItem> implements SysDictItemService {

    private final SysDictService dictService;

    @Override
    public Boolean updateDictItem(SysDictItem dictItem) {
        //先获取字典的系统内置信息
        SysDict dict = dictService.getById(dictItem.getDictId());

        // 判断是不是系统内置的,如果是则抛异常不能修改
        if(!DictTypeEnum.SYSTEM.getType().equals(dict.getSystemFlag())){
            throw new RuntimeException("系统内置字典不能修改");
        }
        //不是系统内置,则进行修改
        this.updateById(dictItem);

        return Boolean.TRUE;
    }

    @Override
    public Boolean deleteDictItem(Long id) {
        // 先根据ID查询字典ID
        SysDictItem dictItem = this.getById(id);
        //再获取字典的系统内置信息
        SysDict dict = dictService.getById(dictItem.getDictId());

        // 判断是不是系统内置的,如果是则抛异常不能修改
        if(!DictTypeEnum.SYSTEM.getType().equals(dict.getSystemFlag())){
            throw new RuntimeException("系统内置字典不允许删除");
        }
        this.removeById(id);

        return Boolean.TRUE;
    }
}

@RestController
@RequestMapping("/dict")
@RequiredArgsConstructor
public class DictController {

    private final SysDictService sysDictService;

    private final SysDictItemService sysDictItemService;


    /**
     * @Description: 修改
     * @param: [dict]
     * @return: com.pig4cloud.pig.common.core.util.R<java.lang.Boolean>
     **/
    @SysLog("修改字典")
    @PutMapping
    @PreAuthorize("@pms.hasPermission('sys_dict_update')")
    public R<Boolean> update(@RequestBody SysDict dict) {

        //标签必须唯一,先判断是否已存在未删除的、该标签
        SysDict sysDict = sysDictService.getOne(Wrappers.<SysDict>lambdaQuery().eq(SysDict::getDictType, dict.getDictType()).ne(SysDict::getId, dict.getId()));
        if ( sysDict != null){
            return R.failed("标签已存在");
        }

        return R.ok(sysDictService.updateDict(dict));
    }

    /**
     * @Description: 删除
     * @param: [dict]
     * @return: com.pig4cloud.pig.common.core.util.R<java.lang.Boolean>
     **/
    @SysLog("删除字典")
    @DeleteMapping("/{id:\\d+}")
    @PreAuthorize("@pms.hasPermission('sys_dict_del')")
    public R<Boolean> deleteDictById(@PathVariable Long id) {
        return R.ok(sysDictService.deleteDict(id));
    }


    /**
     * @Description: 修改
     * @param: [dictItem]
     * @return: com.pig4cloud.pig.common.core.util.R<java.lang.Boolean>
     **/
    @SysLog("修改字典项")
    @PutMapping("/item")
    public R<Boolean> update(@RequestBody SysDictItem dictItem) {

        //value 必须唯一,先判断当前字典中是否已存在该 value
        SysDictItem sysDictItem = sysDictItemService.getOne(
                Wrappers.<SysDictItem>lambdaQuery().eq(SysDictItem::getDictType, dictItem.getDictType()).eq(SysDictItem::getValue, dictItem.getValue()).ne(SysDictItem::getId, dictItem.getId()));
        if ( sysDictItem != null){
            return R.failed("值已存在");
        }

        return R.ok(sysDictItemService.updateDictItem(dictItem));
    }

    /**
     * @Description: 删除
     * @param: [id]
     * @return: com.pig4cloud.pig.common.core.util.R<java.lang.Boolean>
     **/
    @SysLog("删除字典项")
    @DeleteMapping("/item/{id:\\d+}")
    public R<Boolean> deleteDictItemById(@PathVariable Long id) {
        return R.ok(sysDictItemService.deleteDictItem(id));
    }

}

B3.测试

然后就按照 api 接口测试吧,后面要学一下 api 自动化测试~ 

建立字典库_alibaba inc「建议收藏」

遇到的问题:

1.基础增删改查需要判断是否存在

对于普通的单表,增删改查的业务中,如果遇到非正常操作怎么办?

例如,单表中有唯一数据时,改中要校验唯一数据是否存在(自己本身包含不算)。如果入参的 id 不存在或者已删除怎么办?还需要修改么?

从单账号操作的设计上来说,不会出现这种情况,毕竟操作的数据一定是未删除的。但是如果是多账号使用时,就会多个帐号同时删除此条数据,总有一个人成功,而其余人会失败,失败的人也要收到反馈信息。

此时的反馈信息不应该是 500 报错的。

看下图,我用多个线程来调用删除字典的操作,就有一个报错了,虽然最终的数据是对的。

原因是 controller 里面的判断,他通过,但是 service 里面再获取时就获取到了 null。所以还是要处理一下该异常。

建立字典库_alibaba inc「建议收藏」

新建一个业务异常处理类,然后可以在此处用 try catch 异常并抛出新增的业务异常处理类。

@Slf4j
@Order(10000)
@RestControllerAdvice
@ConditionalOnExpression("!'${security.oauth2.client.clientId}'.isEmpty()")
public class GlobalBizExceptionHandler {

	/**
	 * 全局异常.
	 * @param e the e
	 * @return R
	 */
	@ExceptionHandler(Exception.class)
	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
	public R handleGlobalException(Exception e) {
		log.error("全局异常信息 ex={}", e.getMessage(), e);

		// 业务异常交由 sentinel 记录
		Tracer.trace(e);
		return R.failed(e.getLocalizedMessage());
	}

}

 这样就不会报错 500 了建立字典库_alibaba inc「建议收藏」

 

2.增删改查业务添加一个同意逻辑处理模块

写这一块儿的时候,总是修修改改,写某个接口时总感觉逻辑缺少,所以,整理一个基础的单表增删改查逻辑,方便开发理解。

开个新文章,到时粘个链接~

今天的文章建立字典库_alibaba inc「建议收藏」分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/87817.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注