一次bug的处理过程-OA重复档案的问题

1、有的用户无法新增,昨天已经提交该问题,需尽快处理,目前有人入职但是无法使用OA

2、有的用户新增后,出现了如下的情况,同一个用户出现两条记录(具体如下图),造成该用户无法登陆;但是生成了该员工的档案,但是查看详情时,却又无法看到数据,都是空档案;

  这些问题的出现跟最近新上线的功能即新建系统用户直接创建空档案功能有关(仅包括工号、用户名、姓名以及自动创建标识)。

  对于问题1,我们直接远程调试到生产系统,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
UserEntity userEntity = userService.queryUserByStaffId(staffinfoEntity.getStaffId());
        if (userEntity != null) {
            boolean isOk = userService.updateUserInfoforDefine4(userEntity.getUserCode(), "updateNofiles");
            if(isOk) {
                code = staffinfoDao.add(staffinfoEntity);
            }
            try {
                moduleProxyService.updateUserAndLdapAdByStaffInfo(staffinfoEntity);
            catch (Exception e) {
                throw new StaffInfoException("新增档案失败" + e.getMessage());
            }
        else {
            code = staffinfoDao.add(staffinfoEntity);
        }

  在第一行查询时,user只有一个。然后我们进到updateUserAndLdapAdByStaffinfo方法中,该方法第一行即为根据工号查询用户。此时系统则报出错误。我们使用mybatis的selectOne,但是结果集却为两个。我们开始查询user表发现并不存在对应新增staffid的用户,因为事务在此处并未提交,这是没有问题的。但事务并未提交,在前一句还查的是一条,为什么在这里就变成了两条。在这两句中间只有一句话,那就是插入了一条档案数据。那就是在事务中档案及用户数据都应该是一条。

  我们打开对应queryUserByStaffId的方法,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- 按员工工号查询  -->
    <select id="queryUserByStaffId" resultMap="UserResultMap"  parameterType="String">
        SELECT 
        <include refid="UserAll_column"/>, User.userStatus
        FROM 
        <include refid="User_Staff_View"/> 
        User  
        WHERE User.staffId = #{staffid}
    </select>
    <sql id = "User_Staff_View">
        (SELECT tsu.id,tsu.sortNo,tsu.userCode,tsu.deptCode,tsu.deptName,tsu.userName,tsu.userNamePinying,tsu.sex,tsu.userNameEn,tsu.aliasName,tsu.`password`,tsu.dn,tsu.managementScopeType,tsu.managementScope,
        tsu.accessControl,tsu.createTime,tsu.createUserCode,tsu.bindingIp,tsu.modifyTime,tsu.modifyUserCode,tsu.define1,tsu.define2,tsu.define3,tsu.active,tsu.staffId,tsu.deskMenuSequence,tsu.userStatus,
        tsu.givenName,tsu.sn,tsu.displayname,
        tps.personalEmail AS email,
        tps.phone AS mobile,
        tps.stationNo AS physicalDeliveryOfficeName,
        tps.extensionPhone AS telephoneNumber,
        tps.officeAddress AS l,
        tps.postName AS title,
        tps.directLeaderName AS manager,
        tps.define4 AS define4
       FROM t_sys_user tsu INNER JOIN t_per_staffinfo tps ON tsu.staffId = tps.staffId)
    </sql>   

  这种查询用户的方法源于我们之前的一次优化过程。因为用户和档案信息中存在部分字段重复,我们将user表中与档案信息存在重复的一些字段进行了整理,统一关联到档案表中。因为user表中有一些字段被删除,而在业务中可能又需要这些字段,所以我们加了如User_Staff_View的查询方式。

  负责的工程师首先认为是inner join导致的这个问题,导致出现两条。我马上予以了否认,如果user\staffinfo各只有一条数据,使用inner join不会产生两条查询结果。工程师修改为left join得到的结果也是一样。

  同时,其他的问题不断爆出,出现了问题2,错误原因了也是登陆成功后查询用户信息,因selectOne报出500错误。我在系统中查询同一工号或用户名确实是两条相同的用户信息。于是我问运维同事什么情况下会插入两条相同用户信息。随后在后台数据中我又发现用户记录却只有一条,为什么查询却会出现两条呢?

  问题逐渐聚焦在查询方法上。这个关联查询出现问题可以肯定的是不是用户信息有多条,就是档案信息有多个。但从业务角度讲,用户和档案相对于staffid都是全局唯一的。我查询了档案数据,发现档案果然就是两条——HR在使用OA为新入职员工创建档案使用的是excel导入的追加功能(导入有追加和更新两种,如果选择追加,则不做判断,直接插入新记录),而新上线的功能又会在创建用户时同步创建一个空档案,从而产生两条档案记录,也影响到了用户的查询。

  再回到第一个问题,我们知道,新增用户时在新增用户未完成之前,新增档案动作还没有执行。这时候不仅用户,档案也只是一条未提交事务记录,不可能存在多条。我们进一步确认,发现我们新增用户的那个工号已经在用户表中存在,这个工号曾经被分配给一个放弃入职的新员工,放弃入职后IT并未将其删除,所以在新建用户后,未提交事务中的记录+已存在的记录恰是两条。这个问题的错误导向也直接影响了我们对问题2的分析和判断。

  下面我们看一下inner join\left join\right join三者的区别:三者的定义我们大家都知道,inner join只查出符合条件的记录,left join以左表为基准,right join以右表为基准。我们看看我们这种情况,使用三种join的查询结果,经过测试,都是两条。其实这也是我马上对工程师的判断予以否认的原因。




     本文转自 gaochaojs 51CTO博客,原文链接:http://blog.51cto.com/jncumter/1638134,如需转载请自行联系原作者

上一篇:【HDOJ】4516 威威猫系列故事——因式分解


下一篇:.NET MVC 学习笔记(五)— Data Validation