java 高效递归查询树 find_in_set 处理递归树
建表语句
DROP TABLE IF EXISTS `sys_dept`;
CREATE TABLE `sys_dept` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '部门id',
`parent_id` bigint(20) DEFAULT '0' COMMENT '父部门id',
`ancestors` varchar(256) DEFAULT '' COMMENT '祖级列表',
`dept_name` varchar(64) DEFAULT '' COMMENT '部门名称',
`order_num` int(4) DEFAULT '0' COMMENT '显示顺序',
`status` tinyint(1) DEFAULT '0' COMMENT '部门状态(0正常 1停用)',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`create_user_id` bigint(20) DEFAULT NULL COMMENT '创建人id',
`create_user_name` varchar(64) DEFAULT NULL COMMENT '创建人姓名',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
`update_user_id` bigint(20) DEFAULT NULL COMMENT '修改人id',
`update_user_name` varchar(64) DEFAULT NULL COMMENT '修改人姓名',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `uk_dept_name` (`parent_id`,`dept_name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COMMENT='部门表'; -- ----------------------------
-- Records of sys_dept
-- ----------------------------
BEGIN;
INSERT INTO `sys_dept` VALUES (1, 0, '0', 'XX科技', 0, 0, '2021-10-09 10:31:47', 1, '系统管理员', NULL, NULL, NULL);
INSERT INTO `sys_dept` VALUES (2, 1, '0,1', '商务部', 3, 0, '2021-12-06 15:33:20', 1, '系统管理员', '2021-12-06 15:58:30', 1234, '管理');
INSERT INTO `sys_dept` VALUES (3, 1, '0,1', 'XX关务部', 4, 0, '2021-12-06 15:37:01', 1, '系统管理员', '2021-12-06 15:40:15', 1, '系统管理员');
INSERT INTO `sys_dept` VALUES (4, 1, '0,1', 'XX货主', 6, 0, '2021-12-06 15:38:34', 1, '系统管理员', '2021-12-06 17:17:27', 1, '系统管理员');
INSERT INTO `sys_dept` VALUES (5, 1, '0,1', '技术部', 1, 0, '2021-12-06 15:39:22', 1, '系统管理员', '2021-12-06 15:57:48', 1234, '管理');
INSERT INTO `sys_dept` VALUES (6, 4, '0,1,4', '货主-A', 1, 0, '2021-12-06 16:15:26', 1234, '小A', '2021-12-06 17:16:33', 1, '系统管理员');
INSERT INTO `sys_dept` VALUES (7, 4, '0,1,4', '货主-B', 2, 0, '2021-12-06 16:15:39', 1234, '小A', '2021-12-06 17:17:37', 1, '系统管理员');
INSERT INTO `sys_dept` VALUES (8, 6, '0,1,4,6', '1', 11, 0, '2022-03-16 10:27:28', 1, '系统管理员', '2022-03-16 10:27:37', 1, '系统管理员');
INSERT INTO `sys_dept` VALUES (9, 8, '0,1,4,6,8', '111111', 0, 0, '2022-03-16 10:27:45', 1, '系统管理员', NULL, NULL, NULL);
COMMIT;
新增
@Data
@ApiModel(value = "部门编辑对象", description = "部门编辑请求对象")
public class DeptEditRequest {
@ApiModelProperty(value = "主键id", example = "-1")
@DecimalMin(value = "1", message = "角色id最小为1")
private Long id; @ApiModelProperty(value = "父部门id", example = "-1")
@NotNull(message = "上级部门" + HibernateConstant.NOT_NULL)
@JsonProperty("parent_id")
private Long parentId; @ApiModelProperty(value = "部门名称", example = "IT部")
@NotBlank(message = "部门名称" + HibernateConstant.NOT_NULL)
@JsonProperty("dept_name")
private String deptName; @ApiModelProperty(value = "显示顺序", example = "0")
@NotNull(message = "显示" + HibernateConstant.NOT_NULL)
@JsonProperty("order_num")
private Integer orderNum; @ApiModelProperty(value = "部门状态(0正常 1停用)", example = "0")
@Min(value = 0, message = "部门状态(0正常 1停用)")
@Max(value = 1, message = "部门状态(0正常 1停用)")
private byte status;
}
@ApiOperation("部门添加")
@PostMapping("add")
public JsonData add(
@RequestBody DeptAddRequest request
) {
return deptService.add(request);
}
@Override
public JsonData add(DeptAddRequest request) {
DeptEditRequest deptEditRequest = new DeptEditRequest();
BeanUtils.copyProperties(request, deptEditRequest);
//同级部门下,部门名称重复
checkDeptNameUnique(deptEditRequest);
DeptDO deptDO = new DeptDO();
deptDO.setDeptName(request.getDeptName());
deptDO.setParentId(request.getParentId());
deptDO.setStatus(request.getStatus());
deptDO.setOrderNum(request.getOrderNum());
deptDO.setCreateTime(CommonUtil.getCurrentDate());
deptDO.setCreateUserId(CommonUtil.getCurrentUserId());
deptDO.setCreateUserName(CommonUtil.getCurrentUserName());
//检查上级部门状态
checkParentDeptState(deptDO);
int rows = deptMapper.add(deptDO);
if (rows > 0) {
log.info("部门添加,rows:{},添加成功:{}", rows, deptDO);
return JsonData.buildAddSuccess();
}
return JsonData.buildError("添加失败");
} /**
* 部门名称唯一值
*
* @param request
*/
private void checkDeptNameUnique(DeptEditRequest request) {
List<DeptDO> deptList = deptMapper.selectList(
new LambdaQueryWrapper<DeptDO>()
.eq(DeptDO::getDeptName, request.getDeptName())
.eq(DeptDO::getParentId, request.getParentId())
);
for (DeptDO deptDO : deptList) {
if (deptDO.getId() != request.getId()) {
throw new BizException(500, "部门已存在");
}
}
} /**
* 检查上级部门状态
*
* @param dept 部门对象
*/
private void checkParentDeptState(DeptDO dept) {
DeptDO deptDO = deptMapper.selectOne(
new LambdaQueryWrapper<DeptDO>()
.eq(DeptDO::getId, dept.getParentId())
);
if (deptDO == null) {
throw new BizException(500, "上级部门不存在");
}
if (1 == deptDO.getStatus()) {
throw new BizException(500, "上级部门已停用,不允许新增");
}
dept.setAncestors(deptDO.getAncestors() + "," + dept.getParentId());
}
编辑
@Data
@ApiModel(value = "部门编辑对象", description = "部门编辑请求对象")
public class DeptEditRequest {
@ApiModelProperty(value = "主键id", example = "-1")
@DecimalMin(value = "1", message = "角色id最小为1")
private Long id; @ApiModelProperty(value = "父部门id", example = "-1")
@NotNull(message = "上级部门" + HibernateConstant.NOT_NULL)
@JsonProperty("parent_id")
private Long parentId; @ApiModelProperty(value = "部门名称", example = "IT部")
@NotBlank(message = "部门名称" + HibernateConstant.NOT_NULL)
@JsonProperty("dept_name")
private String deptName; @ApiModelProperty(value = "显示顺序", example = "0")
@NotNull(message = "显示" + HibernateConstant.NOT_NULL)
@JsonProperty("order_num")
private Integer orderNum; @ApiModelProperty(value = "部门状态(0正常 1停用)", example = "0")
@Min(value = 0, message = "部门状态(0正常 1停用)")
@Max(value = 1, message = "部门状态(0正常 1停用)")
private byte status;
}
@ApiOperation("部门修改")
@PostMapping("edit")
public JsonData edit(
@RequestBody DeptEditRequest request
) {
if (request.getId() == 1) {
throw new BizException(500, "不允许操作系统默认部门");
}
return deptService.edit(request);
}
@Override
@Transactional
public JsonData edit(DeptEditRequest request) {
DeptDO deptDO = new DeptDO();
BeanUtils.copyProperties(request, deptDO);
//同级部门下,部门名称重复
checkDeptNameUnique(request);
//检查上级部门状态
checkParentDeptState(deptDO);
//上级部门不能是自己
checkParentDept(request);
//父级对象
DeptDO parentDept = deptMapper.selectOne(
new LambdaQueryWrapper<DeptDO>()
.eq(DeptDO::getId, deptDO.getParentId())
);
if (parentDept == null) {
throw new BizException(500, "上级部门不存在");
}
DeptDO oldDept = deptMapper.selectOne(
new LambdaQueryWrapper<DeptDO>()
.eq(DeptDO::getId, deptDO.getId())
);
if (oldDept == null) {
throw new BizException(500, "记录不存在,请稍后重试");
}
String newAncestors = parentDept.getAncestors() + "," + parentDept.getId();
String oldAncestors = oldDept.getAncestors();
deptDO.setAncestors(newAncestors);
byte oldState = oldDept.getStatus();
int rows = deptMapper.updateById(deptDO);
if (rows > 0) {
log.info("部门修改,rows:{},修改成功:{}", rows, deptDO);
//递归处理子部门状态
if (oldState != deptDO.getStatus()) {
updateChildDeptState(deptDO, newAncestors, oldAncestors);
}
return JsonData.buildEditSuccess();
}
return JsonData.buildError("修改失败");
} /**
* 部门名称唯一值
*
* @param request
*/
private void checkDeptNameUnique(DeptEditRequest request) {
List<DeptDO> deptList = deptMapper.selectList(
new LambdaQueryWrapper<DeptDO>()
.eq(DeptDO::getDeptName, request.getDeptName())
.eq(DeptDO::getParentId, request.getParentId())
);
for (DeptDO deptDO : deptList) {
if (deptDO.getId() != request.getId()) {
throw new BizException(500, "部门已存在");
}
}
} /**
* 检查上级部门状态
*
* @param dept 部门对象
*/
private void checkParentDeptState(DeptDO dept) {
DeptDO deptDO = deptMapper.selectOne(
new LambdaQueryWrapper<DeptDO>()
.eq(DeptDO::getId, dept.getParentId())
);
if (deptDO == null) {
throw new BizException(500, "上级部门不存在");
}
if (1 == deptDO.getStatus()) {
throw new BizException(500, "上级部门已停用,不允许新增");
}
dept.setAncestors(deptDO.getAncestors() + "," + dept.getParentId());
} /**
* 上级部门不能是自己
*
* @param request
*/
private void checkParentDept(DeptEditRequest request) {
if (request.getId().equals(request.getParentId())) {
throw new BizException(500, "上级部门不能是自己");
}
} /**
* 处理子部门状态
*
* @param deptDO 部门对象
* @param newAncestors 新的父ID集合
* @param oldAncestors 旧的父ID集合
*/
private void updateChildDeptState(DeptDO deptDO, String newAncestors, String oldAncestors) {
deptMapper.batchUpdateChildDeptState(deptDO.getId(), deptDO.getStatus());
//找所有子部门
List<DeptDO> deptList = deptMapper.selectChildrenDeptById(deptDO.getId());
for (DeptDO dpt : deptList) {
dpt.setAncestors(dpt.getAncestors().replaceFirst(oldAncestors, newAncestors));
deptMapper.updateById(dpt);
}
}
/**
* 批量更新子部门状态
*
* @param id 部门id
* @param state 状态
* @return
*/
int batchUpdateChildDeptState(
@Param("id") Long id,
@Param("state") Byte state
); <!-- 批量更新子部门状态 -->
<update id="batchUpdateChildDeptState">
UPDATE
sys_dept
SET
`status`=#{state}
WHERE ancestors LIKE CONCAT('%',#{id},'%')
</update> /**
* 根据id找所有子部门
*
* @param id
* @return
*/
List<DeptDO> selectChildrenDeptById(@Param("id") Long id); <!-- 根据id找所有子部门 -->
<select id="selectChildrenDeptById" resultMap="BaseResultMap">
SELECT
id,
parent_id,
ancestors,
dept_name,
order_num,
`status`,
create_time,
create_user_id,
create_user_name,
update_time,
update_user_id,
update_user_name
FROM
sys_dept
WHERE
FIND_IN_SET(#{id},ancestors)
</select>
删除
@ApiOperation("部门删除")
@GetMapping("remove")
public JsonData remove(
@ApiParam(value = "部门id", required = true) @RequestParam(value = "id", required = true) Long id
) {
if (id == 1) {
throw new BizException(500, "不允许操作系统默认部门");
}
return deptService.remove(id);
}
@Override
public JsonData remove(Long id) {
int rows = deptMapper.deleteById(id);
if (rows > 0) {
log.info("部门删除,rows:{},删除成功:{}", rows, id);
//递归删除子部门
removeChildDept(id);
return JsonData.buildRemoveSuccess();
}
return JsonData.buildError("部门删除失败");
} /**
* 删除子部门
*
* @param parentId
*/
private void removeChildDept(Long parentId) {
List<DeptDO> deptList = deptMapper.selectList(
new LambdaQueryWrapper<DeptDO>()
.eq(DeptDO::getParentId, parentId)
);
for (DeptDO deptDO : deptList) {
deptMapper.deleteById(deptDO.getId());
removeChildDept(deptDO.getId());
}
}
递归树
@Data
@ApiModel(value = "DeptTreeVo对象", description = "部门树对象信息")
public class DeptTreeVo {
@ApiModelProperty("节点id")
@JsonSerialize(using = ToStringSerializer.class)
private Long id; @ApiModelProperty("节点名称")
private String label; @ApiModelProperty("子节点")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<DeptTreeVo> children;
}
@ApiOperation("部门树")
@GetMapping("deptTree")
public JsonData<List<DeptTreeVo>> deptTree() {
return deptService.deptTree();
}
private static final ThreadPoolExecutor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(
APS * 2,
APS * 4,
KEEP_ALIVE_TIME,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(256),
new ThreadFactoryBuilder().setNameFormat("部门-pool-%d").build(),
new ThreadPoolExecutor.CallerRunsPolicy()
); @Override
public JsonData<List<DeptTreeVo>> deptTree() {
LambdaQueryWrapper<DeptDO> wrapper = new LambdaQueryWrapper<DeptDO>();
wrapper.orderByAsc(DeptDO::getParentId, DeptDO::getOrderNum);
List<DeptDO> deptList = deptMapper.selectList(wrapper);
return buildDeptTree(deptList);
} /**
* 构建前端需要构建树结构
*
* @param deptList 部门集合
* @return
*/
private JsonData<List<DeptTreeVo>> buildDeptTree(List<DeptDO> deptList) {
List<DeptTreeVo> deptTreeList = new ArrayList<>();
List<DeptDO> rootDeptList = deptList.stream().filter(obj -> 1 == obj.getId()).collect(Collectors.toList());
CountDownLatch latch = new CountDownLatch(rootDeptList.size());
for (DeptDO deptDO : rootDeptList) {
THREAD_POOL_EXECUTOR.execute(() -> {
DeptTreeVo vo = new DeptTreeVo();
vo.setId(deptDO.getId());
vo.setLabel(deptDO.getDeptName());
buildChildrentDeptTree(deptList, deptDO.getId(), vo);
deptTreeList.add(vo);
latch.countDown();
});
}
try {
latch.await();
} catch (InterruptedException e) {
log.error("构建部门树结构线程报错:{}", e);
}
return JsonData.buildSuccess(deptTreeList);
} /**
* 构建子部门树
*
* @param deptList 部门集合
* @param parentId 父ID
* @param vo 部门树
*/
private void buildChildrentDeptTree(List<DeptDO> deptList, Long parentId, DeptTreeVo vo) {
List<DeptDO> childList = deptList.stream().filter(obj -> parentId == obj.getParentId()).collect(Collectors.toList());
List<DeptTreeVo> childDeptTreeList = new ArrayList<>();
for (DeptDO deptDO : childList) {
DeptTreeVo dtv = new DeptTreeVo();
dtv.setId(deptDO.getId());
dtv.setLabel(deptDO.getDeptName());
buildChildrentDeptTree(deptList, deptDO.getId(), dtv);
childDeptTreeList.add(dtv);
}
vo.setChildren(childDeptTreeList);
} @Data
@TableName("sys_dept")
@ApiModel(value = "SysDeptDO对象", description = "部门表")
public class DeptDO implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "部门id")
@TableId(value = "id", type = IdType.AUTO)
private Long id; @ApiModelProperty(value = "父部门id")
private Long parentId; @ApiModelProperty(value = "祖级列表")
private String ancestors; @ApiModelProperty(value = "部门名称")
private String deptName; @ApiModelProperty(value = "显示顺序")
private Integer orderNum; @ApiModelProperty(value = "部门状态(0正常 1停用)")
private byte status; @ApiModelProperty(value = "创建时间")
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime; @ApiModelProperty(value = "创建人id")
@TableField(value = "create_user_id", fill = FieldFill.INSERT)
private Long createUserId; @ApiModelProperty(value = "创建人姓名")
@TableField(value = "create_user_name", fill = FieldFill.INSERT)
private String createUserName; @ApiModelProperty(value = "修改时间")
@TableField(value = "update_time", fill = FieldFill.UPDATE)
private Date updateTime; @ApiModelProperty(value = "修改人id")
@TableField(value = "update_user_id", fill = FieldFill.UPDATE)
private Long updateUserId; @ApiModelProperty(value = "修改人姓名")
@TableField(value = "update_user_name", fill = FieldFill.UPDATE)
private String updateUserName;
}
树通用工具类
/**
* 递归深度
*/
private static final int DEPTH = 20; /**
* 集合转树
* @param treeList 集合
* @param rootId 父节点
* @param <T>
*/
public static <T extends TreeNode<T>> void list2Tree(List<T> treeList,Long rootId){
if (CollUtil.isEmpty(treeList)){
return;
}
if (rootId==null){
throw new Exception("根节点不能为空");
}
List<T> rootList = getRoot(treeList, rootId);
if (CollUtil.isNotEmpty(rootList)){
List<T> result = new LinkedList<>();
rootList.stream().forEach(t-> result.add(getChildNode(t,0,treeList)));
treeList.clear();
treeList.addAll(rootList);
}
} private static <T extends TreeNode<T>> List<T> getRoot(List<T> treeList,Long rootId){
return treeList.stream().filter(t->Objects.equals(t.rootId(),rootId)).collect(Collectors.toList());
} private static <T extends TreeNode<T>> T getChildNode(T t,int depthCount,List<T> treeList){
if (depthCount>DEPTH){
throw new Exception("超过递归限制");
}
List<T> childList = treeList.stream().filter(item -> Objects.equals(item.rootId(), t.nodeId())).collect(Collectors.toList());
if (CollUtil.isNotEmpty(childList)){
int tempCount = ++depthCount;
childList.stream().forEach(child->t.childList().add(getChildNode(child,tempCount,treeList)));
}
return t;
}
import java.util.List; public interface TreeNode<T> {
/**
* 节点id
* @return
*/
Long nodeId(); /**
* 父节点
* @return
*/
Long rootId(); /**
* 子级列表
* @return
*/
List<T> childList();
}
/**
* @description: 树VO
* @author: alex
* @create: 2024-03-16 15:46
*/
@Data
public class XxxxVO implements TreeNode<XxxxVO > { @ApiModelProperty("主键id")
private Long id; @ApiModelProperty("父ID")
private Long parentId; @ApiModelProperty("编码")
private String code; @ApiModelProperty("名称")
private String name; private List<XxxxVO> subList = new LinkedList<>(); @ApiModelProperty("是否尾节点")
private boolean isLastNode; @Override
public Long nodeId() {
return getId();
} @Override
public Long rootId() {
return getParentId();
} @Override
public List<XxxxVO> childList() {
return this.subList;
} public boolean isLastNode() {
return this.subList.size() == 0;
}
}
使用
//数据库中查询出来列表
List<XxxxVO> treeList=new LinkedList<>();
//转换树
TreeUtil.listToTree(treeList,0L);
java 高效递归查询树 find_in_set 处理递归树的更多相关文章
- 【转载】Oracle递归查询:使用prior实现树操作【本文出自叶德华博客】
本文标题:Oracle递归查询:使用prior实现树操作 本文链接:http://yedward.net/?id=41 本文版权归作者所有,欢迎转载,转载请以文字链接的形式注明文章出处. Oracle ...
- Best Coder Round#25 1003 树的非递归访问
虽然官方解释是这题目里的树看作无向无环图,从答案来看还是在“以1作为根节点”这一前提下进行的,这棵树搭建好以后,从叶节点开始访问,一直推到根节点即可——很像动态规划的“自底向上”. 但这棵树的搭建堪忧 ...
- Java数据结构和算法 - 什么是2-3-4树
Q1: 什么是2-3-4树? A1: 在介绍2-3-4树之前,我们先说明二叉树和多叉树的概念. 二叉树:每个节点有一个数据项,最多有两个子节点. 多叉树:(multiway tree)允许每个节点有更 ...
- react封装组织架构递归树
想用react实现一个递归树,但一些框架里面的有些不符合需求,于是自己写了个,功能比较简单,欢迎批评指正.. react实现这样一个组织架构递归树,下级部门的收起和展开,点击部门名称时请求接口获取下级 ...
- Java数据结构和算法(一)树
Java数据结构和算法(一)树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 前面讲到的链表.栈和队列都是一对一的线性结构, ...
- MIT6.006Lec03:插入排序,归并排序,递归树
MIT6.006是算法导论课,Lec03主要讲插入排序,归并排序,以及分析方法(递归树)等. 插入排序,可以分为线性插入排序.二分插入排序,区别在于当把数组中某元素插入到前面的有序列表中时,前者遍历, ...
- java数据结构和算法07(2-3-4树)
上一篇我们大概了解了红黑树到底是个什么鬼,这篇我们可以看看另外一种树-----2-3-4树,看这个树的名字就觉得很奇怪.... 我们首先要知道这里的2.3.4指的是任意一个节点拥有的子节点个数,所以我 ...
- java数据结构和算法08(B树的简单原理)
这一篇首先会说说前面剩余的一点知识2-3树,然后简单说说B树,不写代码,只是简单看看原理吧! 为什么要说一下2-3树呢?了解2-3树之后能更快的了解B树: 1.简单看看2-3树 其实我们学过了前面的2 ...
- 【整理】iview Tree数据格式问题,无限递归树处理数据
iview Tree数据格式问题,无限递归树处理数据 https://juejin.im/post/5b51a8a4e51d455d6825be20
- 递归树处理,配合vue的vueTreeselect组件使用
在项目中经常会使用到tree,并且需要对递归树进行操作. 在vue项目中,使用vue-treeselect插件(https://vue-treeselect.js.org/) 使用中遇到的问题: 1. ...
随机推荐
- 关于sql server导出csv格式文件的身份证号乱码问题处理办法
1.使用SQL Server数据库经常会遇到导出大量数据的情况,例如导出40万条数据,虽然EXCL支持可以放入百万的数据,但是使用数据库复制,粘贴到EXCL表格时,数据库会提示溢出的情况,如下图所示: ...
- SQL Server实战六:T-SQL、游标、存储过程的操作
本文介绍基于Microsoft SQL Server软件,实现数据库T-SQL语言程序设计,以及游标的定义.使用与存储过程的创建.信息查找的方法. 目录 1 计算1-100间所有可被3整除的数的个 ...
- UE4 C++调用手柄震动
近期封装输入相关逻辑,简单归纳下. 蓝图实现 内容界面右键Miscellaneous->Force Feedback Effect,创建力反馈对象并填写相关参数: 然后在蓝图中用Spawn Fo ...
- C语言:将字符逆反排列再输出的问题
代码: #include<stdio.h> #define N 10 int main() { /*输入字符串,str[10],将里面的字符逆反排列,再输出.*/ char ch[N]; ...
- AIRIOT答疑第6期|如何使用二次开发引擎?
灵活扩展,满足客户定制化需求 AIRIOT物联网低代码平台提供丰富的前端.后台服务二次开发接口,具备灵活的组件服务部署与管理能力,对任何功能模块进行二次开发,满足客户各类二次开发需求.支持多种 ...
- 微信公众号,微信小程序,百度小程序免费发放了
小程序免费领取了,是真的免费哦 每人限领一套,100%开源,无后门 免费领取方式直接看tpframe官方网站
- 首次调用u8api遇到的问题总结
1.检索 COM 类工厂中 CLSID 为 {72A6FADA-FE26-46BD-A921-BFD1179C1E1E} 的组件时失败,原因是出现以下错误: 80040154. 解决办法是,把编译 ...
- SQL 分析与优化神器,验证了真相定律
引言 今天要分享的是一个 SQL 语句分析的神器,它是一个基于 Soar 的开源 sql 分析与优化的 Web 图形化工具.我们在平常分析 SQL 语句,使用最多的方式就是 Explain 工具.了解 ...
- Android 13 - Media框架(19)- ACodec(一)
关注公众号免费阅读全文,进入音视频开发技术分享群! 这一节我们将会一起了解 ACodec 的设计方式,在看具体的实现细节前我们要先了解它内部的状态转换机制,这也是ACodec的核心难点之一. 1.AH ...
- 不使用循环语句用if和else实现循环
如果不使用循环语句,可以使用递归函数来实现循环的效果.递归函数是指在函数内部调用自身的函数.下面是一个使用递归函数来实现循环的示例: (初学者记得写include,这里是个普通函数,所以我没写) de ...