思路:
主要是同时操作两张表:一张存储数据的表,一张存储模板字段的表;
查询:只查询模板字段的表;
新增,修改,删除:需要同时操作两张表中的字段
如果两张表字段不一致,可能导致:数据模板,数据导出,导入失败!
案例:
动态模板查询:
备注:查询我们不采用传统的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”)
@Autowired
private 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 {
@Autowired
private 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 {
@Autowired
private ListMapper ListMapper;
/*
*增加/修改:动态模板字段
*
* @param param
* @return
*/
@Override
public 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))
BEGIN
DECLARE altStr VARCHAR(2000);
DECLARE addSql VARCHAR(2000);
IF NOT EXISTS(SELECT 1
FROM information_schema.COLUMNS
WHERE table_name = c_table
AND column_name = c_headerField)
THEN
SET addSql := CONCAT(
'INSERT INTO ',
h_table,
'(headerName, headerField, headerType, headerLength) VALUES("',
c_headerName, '","', c_headerField, '","', c_headerType, '","', c_headerLength, '")'
);
IF (c_headerType = 'VARCHAR')
THEN
SET c_headerType := CONCAT(c_headerType, '(', c_headerLength, ')');
END IF;
SET altStr := CONCAT(
'ALTER TABLE ',
c_table,
' ADD COLUMN ',
c_headerField, ' ', c_headerType
);
ELSE
SET altStr := '';
SET addSql := '';
END IF;
-- 执行命令
IF (altStr <> '')
THEN
SET @SQL1 = altStr ; PREPARE stmt1 FROM @SQL1 ; EXECUTE stmt1 ;
END IF;
IF (addSql <> '')
THEN
SET @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查询!