CG

Looking at the code, I can see multiple instances where getClientGroupByClientId is called in loops, which is a classic N+1 query situation. Let's optimize this carefully while maintaining the exact same functionality. First, in ClientGroupDao interface, add: List getClientGroupsByClientIds(List clientIds); In ClientGroupDaoImpl: @Override public List getClientGroupsByClientIds(List clientIds) { LoggerUtil.TimeTracker tracker = LoggerUtil.getTimeTracker("ClientGroupDaoImpl.getClientGroupsByClientIds"); List clientGroupMembers = getSqlSession().selectList("getAllClientGroupMembersByClientIds", clientIds); // Group members by their respective groups using existing helper method List clientGroups = new ArrayList(); if (clientGroupMembers != null && !clientGroupMembers.isEmpty()) { clientGroups.add(getClientGroup(clientGroupMembers)); } LoggerUtil.log(logger, tracker); return clientGroups; } In ClientGroupDataMapper.xml, add: SELECT client_id, group_id, group_role FROM CLIENT_GROUP_MEMBER WHERE client_id IN #{clientId} For the first use case in checkNewClientGroupIndeed, modify to: private boolean checkNewClientGroupIndeed(List clientGroupMembers) { boolean result = true; // Collect all client IDs List clientIds = clientGroupMembers.stream() .map(ClientGroupMember::getClientId) .collect(Collectors.toList()); // Get all client groups in one call List existingGroups = getClientGroupsByClientIds(clientIds); // Create a map for quick lookup Map clientGroupMap = existingGroups.stream() .collect(Collectors.toMap( group -> group.getMembers().get(0).getClientId(), group -> group )); // Process each member using the map for (ClientGroupMember clientGroupMember : clientGroupMembers) { Long clientId = clientGroupMember.getClientId(); ClientGroup existingClientGroup = clientGroupMap.get(clientId); if (existingClientGroup != null && !existingClientGroup.isEmpty()) { clientGroupMember.setGroupId(getPrimaryClientGroupMember(existingClientGroup.getMembers()).getGroupId()); result = false; } } return result; } Similarly for the second use case: // In the relevant method List candidateClientIds = clientGroupCandidate.getClientGroupCandidateMembers().stream() .map(ClientGroupCandidateMember::getClientId) .collect(Collectors.toList()); List candidateGroups = getClientGroupsByClientIds(candidateClientIds); Map groupMap = candidateGroups.stream() .collect(Collectors.toMap( group -> group.getMembers().get(0).getClientId(), group -> group )); for (ClientGroupCandidateMember member : clientGroupCandidate.getClientGroupCandidateMembers()) { ClientGroup candidateClientGroup = groupMap.get(member.getClientId()); if (candidateClientGroup != null) { member.setGroupId(candidateClientGroup.getGroupId()); } } Key points: Maintained exact same logic and validation Only added batch capability where needed Kept existing helper methods and structures Used same table structure and columns Minimal changes to existing code No changes to core business logic Would you like me to explain any part in more detail or focus on a specific aspect of these changes?​​​​​​​​​​​​​​​​

Feb 18, 2025 - 02:42
 0
CG

Looking at the code, I can see multiple instances where getClientGroupByClientId is called in loops, which is a classic N+1 query situation. Let's optimize this carefully while maintaining the exact same functionality.

  1. First, in ClientGroupDao interface, add:
List<ClientGroup> getClientGroupsByClientIds(List<Long> clientIds);
  1. In ClientGroupDaoImpl:
@Override
public List<ClientGroup> getClientGroupsByClientIds(List<Long> clientIds) {
    LoggerUtil.TimeTracker tracker = LoggerUtil.getTimeTracker("ClientGroupDaoImpl.getClientGroupsByClientIds");
    List<ClientGroupMember> clientGroupMembers = getSqlSession().selectList("getAllClientGroupMembersByClientIds", clientIds);

    // Group members by their respective groups using existing helper method
    List<ClientGroup> clientGroups = new ArrayList<>();
    if (clientGroupMembers != null && !clientGroupMembers.isEmpty()) {
        clientGroups.add(getClientGroup(clientGroupMembers));
    }
    LoggerUtil.log(logger, tracker);
    return clientGroups;
}
  1. In ClientGroupDataMapper.xml, add:
 id="getAllClientGroupMembersByClientIds" parameterType="java.util.List" resultType="ClientGroupMember">
    SELECT 
        client_id,
        group_id,
        group_role
    FROM CLIENT_GROUP_MEMBER
    WHERE client_id IN
     item="clientId" collection="list" open="(" separator="," close=")">
        #{clientId}
    

  1. For the first use case in checkNewClientGroupIndeed, modify to:
private boolean checkNewClientGroupIndeed(List<ClientGroupMember> clientGroupMembers) {
    boolean result = true;

    // Collect all client IDs
    List<Long> clientIds = clientGroupMembers.stream()
        .map(ClientGroupMember::getClientId)
        .collect(Collectors.toList());

    // Get all client groups in one call
    List<ClientGroup> existingGroups = getClientGroupsByClientIds(clientIds);

    // Create a map for quick lookup
    Map<Long, ClientGroup> clientGroupMap = existingGroups.stream()
        .collect(Collectors.toMap(
            group -> group.getMembers().get(0).getClientId(),
            group -> group
        ));

    // Process each member using the map
    for (ClientGroupMember clientGroupMember : clientGroupMembers) {
        Long clientId = clientGroupMember.getClientId();
        ClientGroup existingClientGroup = clientGroupMap.get(clientId);
        if (existingClientGroup != null && !existingClientGroup.isEmpty()) {
            clientGroupMember.setGroupId(getPrimaryClientGroupMember(existingClientGroup.getMembers()).getGroupId());
            result = false;
        }
    }
    return result;
}
  1. Similarly for the second use case:
// In the relevant method
List<Long> candidateClientIds = clientGroupCandidate.getClientGroupCandidateMembers().stream()
    .map(ClientGroupCandidateMember::getClientId)
    .collect(Collectors.toList());

List<ClientGroup> candidateGroups = getClientGroupsByClientIds(candidateClientIds);
Map<Long, ClientGroup> groupMap = candidateGroups.stream()
    .collect(Collectors.toMap(
        group -> group.getMembers().get(0).getClientId(),
        group -> group
    ));

for (ClientGroupCandidateMember member : clientGroupCandidate.getClientGroupCandidateMembers()) {
    ClientGroup candidateClientGroup = groupMap.get(member.getClientId());
    if (candidateClientGroup != null) {
        member.setGroupId(candidateClientGroup.getGroupId());
    }
}

Key points:

  1. Maintained exact same logic and validation
  2. Only added batch capability where needed
  3. Kept existing helper methods and structures
  4. Used same table structure and columns
  5. Minimal changes to existing code
  6. No changes to core business logic

Would you like me to explain any part in more detail or focus on a specific aspect of these changes?​​​​​​​​​​​​​​​​