思路:
主要是同时操作两张表:一张存储数据的表,一张存储模板字段的表;
查询:只查询模板字段的表;
新增,修改,删除:需要同时操作两张表中的字段
如果两张表字段不一致,可能导致:数据模板,数据导出,导入失败!
案例:
动态模板查询:
备注:查询我们不采用传统的SQ查询,而是采用:QueryWrapper 查询
VO类:
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;/*** 动态模板字段*/
@Data
@TableName("list_table_header")
public class ListFormTableVo{private String headerName;private String headerField;private String headerType;private String headerLength;private String isModify;private String isDelete;private String isAuto;private int id;private String colExample;
}
Controller层:ListController
@Slf4j
@RestController
@RequestMapping(“/xxxList”)
@Autowiredprivate ListTempleteService listTempleteService;public Result getListTemplateCell() {QueryWrapper<ListFormTableVo> queryWrapper = new QueryWrapper<>();queryWrapper.orderByAsc("id");// 根据模板字段ID升序排序return Result.success().result(ListTempleteService.list(queryWrapper));}
Service层:ListTempleteService(只写接口层)
public interface ListTempleteService extends IService<ListFormTableVo> {
}
ServiceImpl层:ListTempleteServiceImpl(只写接口层)
@Service
public class ListTempleteServiceImpl extends ServiceImpl<ListFormTemplateMapper,ListFormTableVo> implements ListTempleteService {
}
Mapper层:ListFormTemplateMapper(只写接口层)
@Mapper
public interface ListFormTemplateMapper extends BaseMapper<ListFormTableVo> {
}
至此:整个查询就结束了,是不是比我们常规写SQ简单多呢,当然我们也可以采用常规方式查询!
关于增删改,需要说明一下:
我们在进行增删改的时候:需要操作两张表:
表A,模板表,这张表是操作里面的数据;
表B,数据表,这张表是操作里面的字段列;
操作列的SQ如下:
数据库表 : 添加字段(在表A中,字段c后面添加字段b,字段b中文:中文xxx)
ALTER TABLE 表A ADD 字段b VARCHAR(250) COMMENT ‘中文xxx’ AFTER 字段c;
数据库表 : 删除字段(在表A中,删除字段b)
ALTER TABLE 表A DROP 字段b;
数据库表 : 修改字段属性(在表A中,修改字段isUpdate长度为20,中文为:是否修改)
ALTER TABLE 表A MODIFY COLUMN isUpdate VARCHAR(20) COMMENT ‘是否修改’;
操作数据的SQ自行脑部,不做说明!
需要注意:
我们在增删的时候,要么就是在两张表添加新字段,要么就是在两张表删除新字段;
但是修改字段的时候,一般是修改的是模板表,修改的是模板表里面的数据中文名称,
比如:headerName这一列的数据,比如修改:部门A为:部门AAA,条件是:headerField = hrA;
备注:在进行增删改的时候,一般我们会对初始的字段列做控制,不让进行修改,删除;
只对新增的字段操作:修改,删除,且修改一般也做控制,如:只改中文名称,用于模板回填展示!
动态模板添加修改:(一般都是添加,修改出一个接口)
Controller层:ListController
@Slf4j
@RestController
@RequestMapping("/xxxList")
public class ListController {@Autowiredprivate ListService ListService;/*** 增加/修改:动态模板字段* 权限-管理员** @param param* @return*/@PostMapping(value = "/addOrUpdateListDataCell")@AuthInterceptor("mag:getList:addOrUpdateTemplate")public Result addOrUpdateListDataCell(@RequestBody String param) {try {List<Map<String, Object>> paramList = JsonUtils.readValue(param, List.class);ListService.addOrUpdateListDataCell(paramList);return Result.success();} catch (Exception e) {log.error("===模板增加 addOrUpdateListDataCellis error===:" + e.getMessage(), e);return Result.failure("修改或添加模板失败");}}
Service层:ListService
public interface ListService {//增加/修改:动态模板字段void addOrUpdateListDataCell (List<Map<String, Object>> paramList) throws Exception;
}
ServiceImpl层:ListServiceImpl
@Slf4j
@Service
public class ListServiceImpl implements ListService {@Autowiredprivate ListMapper ListMapper;/**增加/修改:动态模板字段** @param param* @return*/@Overridepublic void addOrUpdateListDataCell (List<Map<String, Object>> paramList) throws Exception {String updateOrSave = String.valueOf((paramList.get("updateOrSave")));// 通过前台传的字段:updateOrSave的值确定是添加还是修改; // 添加if (updateOrSave.equals("save")){paramList.remove("updateOrSave"); // 数据库不需要该字段,删除,根据SQ看是否需要删除这一行代码;ListMapper.addListDataCell(paramList);}// 修改if(updateOrSave.equals("update")){ListMapper.updateListDataCell(modifys);}}
Mapper层:ListMapper
@Mapper
public interface ListMapper {//增加:动态模板字段void addListDataCell(List<Map<String, Object>> paramList);//修改:动态模板字段void updateListDataCell(List<Map<String, Object>> paramList);}
Mapper.xml:ListMapper.xml
ListMapper.xml里面可以写SQ,写可以通过存储过程执行SQ,本文采用存储过程添加字段!
<!-- 增加:动态模板字段 --><insert id="addListDataCell" parameterType="java.util.List"><foreach collection="list" item="item" index="index">CALL add_template(#{item.headerField},#{item.headerLength},#{item.headerName},#{item.headerType},'list_form_data','list_table_header');</foreach></insert><!-- 修改:动态模板字段 --><update id="updateListDataCell" parameterType="java.util.List"><foreach collection="list" item="item" index="i" separator=";">update list_table_header<set>headerName = #{item.headerName}</set>WHERE 1=1<if test="null!= item.headerField and ''!= item.headerField">AND headerField = #{item.headerField}</if></foreach></update>
存储过程语法:
DELIMITER $$USE `xx_control_schema`$$DROP PROCEDURE IF EXISTS `add_template`$$CREATE DEFINER=`root`@`localhost` PROCEDURE `add_template`(c_headerField VARCHAR(1000), c_headerLength VARCHAR(1000),c_headerName VARCHAR(1000), c_headerType VARCHAR(1000), c_table VARCHAR(200),h_table VARCHAR(1000))
BEGINDECLARE altStr VARCHAR(2000);DECLARE addSql VARCHAR(2000);IF NOT EXISTS(SELECT 1FROM information_schema.COLUMNSWHERE table_name = c_tableAND column_name = c_headerField)THENSET addSql := CONCAT('INSERT INTO ',h_table,'(headerName, headerField, headerType, headerLength) VALUES("',c_headerName, '","', c_headerField, '","', c_headerType, '","', c_headerLength, '")');IF (c_headerType = 'VARCHAR')THENSET c_headerType := CONCAT(c_headerType, '(', c_headerLength, ')');END IF;SET altStr := CONCAT('ALTER TABLE ',c_table,' ADD COLUMN ',c_headerField, ' ', c_headerType);ELSESET altStr := '';SET addSql := '';END IF;-- 执行命令IF (altStr <> '')THENSET @SQL1 = altStr ; PREPARE stmt1 FROM @SQL1 ; EXECUTE stmt1 ;END IF;IF (addSql <> '')THENSET @SQL2 = addSql ; PREPARE stmt2 FROM @SQL2 ; EXECUTE stmt2 ;END IF;
END$$DELIMITER ;
使用存储过程:添加只需要写一个接口即可,如果通过编写SQ,则写两个添加接口的SQ也可以实现!
// 添加if (updateOrSave.equals("save")){paramList.remove("updateOrSave"); // 数据库不需要该字段,删除,根据SQ看是否需要删除这一行代码;ListMapper.addListTableHeader(paramList); // 模板表 添加字段(数据)ListMapper.addListFormData(paramList); // 数据表 添加字段列}
动态模板删除:同理,代码比较简单,可自行编写哈!
至此,动态模板字段的增删改查就完成了!
总结:本文我们使用了两项不常用的技术:存储过程,QueryWrapper查询!