建表语句

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 处理递归树的更多相关文章

  1. 【转载】Oracle递归查询:使用prior实现树操作【本文出自叶德华博客】

    本文标题:Oracle递归查询:使用prior实现树操作 本文链接:http://yedward.net/?id=41 本文版权归作者所有,欢迎转载,转载请以文字链接的形式注明文章出处. Oracle ...

  2. Best Coder Round#25 1003 树的非递归访问

    虽然官方解释是这题目里的树看作无向无环图,从答案来看还是在“以1作为根节点”这一前提下进行的,这棵树搭建好以后,从叶节点开始访问,一直推到根节点即可——很像动态规划的“自底向上”. 但这棵树的搭建堪忧 ...

  3. Java数据结构和算法 - 什么是2-3-4树

    Q1: 什么是2-3-4树? A1: 在介绍2-3-4树之前,我们先说明二叉树和多叉树的概念. 二叉树:每个节点有一个数据项,最多有两个子节点. 多叉树:(multiway tree)允许每个节点有更 ...

  4. react封装组织架构递归树

    想用react实现一个递归树,但一些框架里面的有些不符合需求,于是自己写了个,功能比较简单,欢迎批评指正.. react实现这样一个组织架构递归树,下级部门的收起和展开,点击部门名称时请求接口获取下级 ...

  5. Java数据结构和算法(一)树

    Java数据结构和算法(一)树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 前面讲到的链表.栈和队列都是一对一的线性结构, ...

  6. MIT6.006Lec03:插入排序,归并排序,递归树

    MIT6.006是算法导论课,Lec03主要讲插入排序,归并排序,以及分析方法(递归树)等. 插入排序,可以分为线性插入排序.二分插入排序,区别在于当把数组中某元素插入到前面的有序列表中时,前者遍历, ...

  7. java数据结构和算法07(2-3-4树)

    上一篇我们大概了解了红黑树到底是个什么鬼,这篇我们可以看看另外一种树-----2-3-4树,看这个树的名字就觉得很奇怪.... 我们首先要知道这里的2.3.4指的是任意一个节点拥有的子节点个数,所以我 ...

  8. java数据结构和算法08(B树的简单原理)

    这一篇首先会说说前面剩余的一点知识2-3树,然后简单说说B树,不写代码,只是简单看看原理吧! 为什么要说一下2-3树呢?了解2-3树之后能更快的了解B树: 1.简单看看2-3树 其实我们学过了前面的2 ...

  9. 【整理】iview Tree数据格式问题,无限递归树处理数据

    iview Tree数据格式问题,无限递归树处理数据 https://juejin.im/post/5b51a8a4e51d455d6825be20

  10. 递归树处理,配合vue的vueTreeselect组件使用

    在项目中经常会使用到tree,并且需要对递归树进行操作. 在vue项目中,使用vue-treeselect插件(https://vue-treeselect.js.org/) 使用中遇到的问题: 1. ...

随机推荐

  1. Spring Cloud 部署时如何使用 Kubernetes 作为注册中心和配置中心

    一.Spring Cloud 支持的常见注册中心和配置中心. Spring Cloud 自带的注册中心Eureka以及config配置中心 Nacos,支持注册中心和配置中心等,可以参考:https: ...

  2. 23ai免费版本环境快速就绪

    笔者感受就是搞一套Oracle 23ai的学习测试环境,从未如此的简单高效. 因为近期Oracle 23ai这个话题很火,很多人也在找实验环境想亲自体验测试一番. 其实搞这样的环境没有任何的门槛,甚至 ...

  3. Linux下mv和cp命令的区别

    1.功能上的区别 ​ mv:用户可以使用mv为文件或目录重命名或将文件由一个目录移入另一个目录中. ​ cp: cp的功能是将给出的文件或目录拷贝到另一文件或目录中. 2.inode上的区别(inod ...

  4. 干货 springcloud之 poenFeign的使用

    PoenFeign集成到springcloud项目中 先创建一个springboot项目 这里就不多说了 application.yml文件: server: port: 8082spring: ap ...

  5. FMEA学习之PFMEA

    一.基础介绍 FMEA 是 Faliure Mode Effect Analysis 简称,翻译过来叫做失效模式分析,按我的理解,用白话说出来就是:对导致不符合生产质量不符合客户要求的问题会产生多么严 ...

  6. RocketMQ主从同步原理

    一. 主从同步概述 主从同步这个概念相信大家在平时的工作中,多少都会听到.其目的主要是用于做一备份类操作,以及一些读写分离场景.比如我们常用的关系型数据库mysql,就有主从同步功能在. 主从同步,就 ...

  7. JDK8之前,匿名内部类访问的局部变量为什么必须要用final修饰

    更多博文请关注:https://blog.bigcoder.cn 前不久在学习中意外发现了自己原来忽略的一个小知识点,挺有意思的,现在我来给大家分享一下! 我们先来看一段代码 public class ...

  8. OpenCV简单实现AR需用到的算法函数介绍

    目前的AR需求(想要达到的目标) 公司目前的需求是要能够指定一个物体开始追踪,将一张预先准备好的图像覆盖在被追踪的物体上, 然后镜头偏转缩放各类操作,再转回来仍然可以识别到,并且同样依旧覆盖图片到先前 ...

  9. Unity 3D 的NEW (堆内存)

    用容器装 在AWEKE NEW 运行时NEW 会导致分配内存时界面卡住, new class 的时候 才刷新程序帧 AWEKE 是程序启动时还没走完第一帧的开头执行 AWEKE 里面的代码 常量也在A ...

  10. C# .NET MVC 表单提交前校验数据等

    页面上写2个button,一个普通button,另一个是submit,submit的这个隐藏.校验函数写在普通button里,普通button click函数中去提交表单. 页面: <input ...