@Override
    public List<ConfigInfo> removeConfigInfoByIds(final List<Long> ids, final String srcIp, final String srcUser) {
        if (CollectionUtils.isEmpty(ids)) {
            return null;
        }
        ids.removeAll(Collections.singleton(null));
        return tjt.execute(new TransactionCallback<List<ConfigInfo>>() {
            final Timestamp time = new Timestamp(System.currentTimeMillis());
            
            @Override
            public List<ConfigInfo> doInTransaction(TransactionStatus status) {
                try {
                    String idsStr = StringUtils.join(ids, StringUtils.COMMA);
                    List<ConfigInfo> configInfoList = findConfigInfosByIds(idsStr);
                    if (!CollectionUtils.isEmpty(configInfoList)) {
                        removeConfigInfoByIdsAtomic(idsStr);
                        for (ConfigInfo configInfo : configInfoList) {
                            removeTagByIdAtomic(configInfo.getId());
                            historyConfigInfoPersistService.insertConfigHistoryAtomic(configInfo.getId(), configInfo,
                                    srcIp, srcUser, time, "D");
                        }
                    }
                    return configInfoList;
                } catch (CannotGetJdbcConnectionException e) {
                    LogUtil.FATAL_LOG.error("[db-error] " + e, e);
                    throw e;
                }
            }
        });
    }
@Test
    void testRemoveConfigInfoByIds() {
        
        //mock exist config info
        List<ConfigInfo> configInfos = new ArrayList<>();
        configInfos.add(new ConfigInfo("data1", "group", "tenant", "app", "content"));
        configInfos.add(new ConfigInfo("data2", "grou2", "tenan2", "app2", "content2"));
        List<Long> deleteIds = Arrays.asList(12344L, 3456789L);
        configInfos.get(0).setId(12344L);
        configInfos.get(1).setId(3456789L);
        Mockito.when(jdbcTemplate.query(anyString(), eq(deleteIds.toArray()), eq(CONFIG_INFO_ROW_MAPPER))).thenReturn(configInfos);
        String srcIp = "srcIp1234";
        String srcUser = "srcUser";
        externalConfigInfoPersistService.removeConfigInfoByIds(deleteIds, srcIp, srcUser);
        
        //expect delete to be invoked
        Mockito.verify(jdbcTemplate, times(1)).update(anyString(), eq(deleteIds.get(0)), eq(deleteIds.get(1)));
        //expect delete tags to be invoked
        Mockito.verify(jdbcTemplate, times(1)).update(anyString(), eq(deleteIds.get(0)));
        Mockito.verify(jdbcTemplate, times(1)).update(anyString(), eq(deleteIds.get(1)));
        //expect insert delete history
        Mockito.verify(historyConfigInfoPersistService, times(1))
                .insertConfigHistoryAtomic(eq(configInfos.get(0).getId()), eq(configInfos.get(0)), eq(srcIp), eq(srcUser), any(), eq("D"));
        Mockito.verify(historyConfigInfoPersistService, times(1))
                .insertConfigHistoryAtomic(eq(configInfos.get(1).getId()), eq(configInfos.get(1)), eq(srcIp), eq(srcUser), any(), eq("D"));
        
    }