编辑 | blame | 历史 | 原始文档

部门分公司ID获取方法说明

概述

新增了独立的方法 selectBranchCompanyIdByDeptId,用于获取指定部门ID对应的分公司ID(parent_id=100的部门)。

方法定义

Mapper接口

文件: SysDeptMapper.java

/**
 * 获取指定部门ID的分公司ID(parent_id=100的部门)
 * 如果传入的就是分公司,直接返回;否则从ancestors中查找分公司ID
 * 
 * @param deptId 部门ID
 * @return 分公司ID,如果找不到则返回null
 */
public Long selectBranchCompanyIdByDeptId(@Param("deptId") Long deptId);

SQL实现

文件: SysDeptMapper.xml

<!-- 获取指定部门ID的分公司ID(parent_id=100的部门) -->
<select id="selectBranchCompanyIdByDeptId" parameterType="Long" resultType="Long">
    select case 
        -- 如果传入的就是分公司(parent_id=100),直接返回
        when exists(select 1 from sys_dept where dept_id = #{deptId} and parent_id = 100 and del_flag = '0') 
        then #{deptId}
        else (
            -- 否则从 ancestors 中查找分公司ID
            select d.dept_id
            from sys_dept d
            where d.parent_id = 100
            and d.del_flag = '0'
            and FIND_IN_SET(d.dept_id, (
                select ancestors from sys_dept where dept_id = #{deptId} and del_flag = '0'
            ))
            limit 1
        )
    end
</select>

使用示例

在Service层中使用

@Autowired
private SysDeptMapper deptMapper;

public void someMethod(Long deptId) {
    // 获取分公司ID
    Long branchCompanyId = deptMapper.selectBranchCompanyIdByDeptId(deptId);
    
    if (branchCompanyId != null) {
        // 使用分公司ID进行后续操作
        System.out.println("分公司ID: " + branchCompanyId);
    } else {
        // 找不到分公司(可能是总公司或数据异常)
        System.out.println("未找到分公司ID");
    }
}

在MyBatis XML中使用

可以在其他Mapper的SQL中作为子查询使用:

<select id="someQuery" resultType="SomeType">
    SELECT * FROM some_table
    WHERE dept_id = (
        SELECT CASE 
            WHEN EXISTS(SELECT 1 FROM sys_dept WHERE dept_id = #{deptId} AND parent_id = 100 AND del_flag = '0') 
            THEN #{deptId}
            ELSE (
                SELECT d.dept_id
                FROM sys_dept d
                WHERE d.parent_id = 100
                AND d.del_flag = '0'
                AND FIND_IN_SET(d.dept_id, (
                    SELECT ancestors FROM sys_dept WHERE dept_id = #{deptId} AND del_flag = '0'
                ))
                LIMIT 1
            )
        END
    )
</select>

工作原理

部门结构示例

总公司 (dept_id=100, parent_id=0, ancestors="0")
├── 北京分公司 (dept_id=101, parent_id=100, ancestors="0,100")
│   ├── 技术部 (dept_id=201, parent_id=101, ancestors="0,100,101")
│   └── 业务部 (dept_id=202, parent_id=101, ancestors="0,100,101")
└── 上海分公司 (dept_id=102, parent_id=100, ancestors="0,100")
    └── 市场部 (dept_id=203, parent_id=102, ancestors="0,100,102")

查询逻辑

  1. 传入分公司ID (如: deptId=101)
  • 检查 parent_id = 100
  • 直接返回: 101
  1. 传入子部门ID (如: deptId=201)
  • 检查 parent_id = 100
  • 查询 ancestors = "0,100,101"
  • 使用 FIND_IN_SET 查找 parent_id=100 的部门
  • 找到匹配: 101
  • 返回: 101
  1. 传入总公司ID (如: deptId=100)
  • 检查 parent_id = 100 ❌ (parent_id=0)
  • ancestors中没有parent_id=100的部门
  • 返回: null

应用场景

1. 车辆查询

用户在任意部门,查询时自动定位到所属分公司的车辆:

// 原始实现(VehicleInfoMapper.xml)
Long branchCompanyId = deptMapper.selectBranchCompanyIdByDeptId(userDeptId);
List<VehicleInfo> vehicles = vehicleMapper.selectByDeptId(branchCompanyId);

2. 数据权限过滤

限制用户只能查看所属分公司的数据:

public List<SomeData> getDataList(Long userDeptId) {
    Long branchCompanyId = deptMapper.selectBranchCompanyIdByDeptId(userDeptId);
    return someMapper.selectByBranchCompany(branchCompanyId);
}

3. 报表统计

按分公司维度统计数据:

public Map<String, Object> getStatistics(Long deptId) {
    Long branchCompanyId = deptMapper.selectBranchCompanyIdByDeptId(deptId);
    return statisticsService.getByBranchCompany(branchCompanyId);
}

性能优化建议

1. 添加索引

确保以下字段有索引:
```sql
-- 已有的索引
CREATE INDEX idx_parent_id ON sys_dept(parent_id);
CREATE INDEX idx_del_flag ON sys_dept(del_flag);

-- 建议添加复合索引
CREATE INDEX idx_parent_del ON sys_dept(parent_id, del_flag);
```

2. 结果缓存

对于频繁查询的场景,可以考虑缓存结果:

@Cacheable(value = "branchCompany", key = "#deptId")
public Long getBranchCompanyId(Long deptId) {
    return deptMapper.selectBranchCompanyIdByDeptId(deptId);
}

注意事项

  1. 返回值可能为null
  • 总公司(dept_id=100)查询时会返回null
  • 部门数据异常时也会返回null
  • 使用时需要做空值判断
  1. 只查询正常部门
  • SQL中已过滤 del_flag = '0'
  • 被删除的部门不会被查询到
  1. 分公司定义
  • 分公司必须满足 parent_id = 100
  • 如果组织架构调整,需要确保这个规则仍然适用
  1. ancestors字段维护
  • 部门层级变更时必须更新ancestors字段
  • ancestors格式必须是逗号分隔的ID列表

测试场景

测试用例1: 传入分公司ID

输入: deptId = 101 (北京分公司)
预期输出: 101

测试用例2: 传入子部门ID

输入: deptId = 201 (技术部)
预期输出: 101 (北京分公司)

测试用例3: 传入总公司ID

输入: deptId = 100 (总公司)
预期输出: null

测试用例4: 传入多级子部门ID

输入: deptId = 301 (假设技术部下的小组,ancestors="0,100,101,201")
预期输出: 101 (北京分公司)

更新日志

  • 2025-01-25: 创建独立方法 selectBranchCompanyIdByDeptId
  • 目的: 简化分公司ID查询逻辑,提高代码复用性