public void createQprofileChangesForRuleUpdates(DbSession dbSession, Set<PluginRuleUpdate> pluginRuleUpdates) {
    List<QProfileChangeDto> changesToPersist = pluginRuleUpdates.stream()
      .flatMap(pluginRuleUpdate -> {
        RuleChangeDto ruleChangeDto = createNewRuleChange(pluginRuleUpdate);
        insertRuleChange(dbSession, ruleChangeDto);

        return findQualityProfilesForRule(dbSession, pluginRuleUpdate.getRuleUuid()).stream()
          .map(qualityProfileUuid -> buildQprofileChangeDtoForRuleChange(qualityProfileUuid, ruleChangeDto));
      }).toList();

    if (!changesToPersist.isEmpty()) {
      dbClient.qProfileChangeDao().bulkInsert(dbSession, changesToPersist);
    }
  }
@Test
  public void updateWithoutCommit_whenTwoRulesChangedTheirImpactsAndAttributes_thenInsertRuleChangeAndImpactChange() {
    PluginRuleUpdate pluginRuleUpdate = new PluginRuleUpdate();
    pluginRuleUpdate.setNewCleanCodeAttribute(CleanCodeAttribute.CLEAR);
    pluginRuleUpdate.setOldCleanCodeAttribute(CleanCodeAttribute.TESTED);
    pluginRuleUpdate.setRuleUuid(RULE_UUID);

    //testing here detecting the change with 2 the same software qualities
    pluginRuleUpdate.addNewImpact(SoftwareQuality.RELIABILITY, Severity.LOW);
    pluginRuleUpdate.addOldImpact(SoftwareQuality.RELIABILITY, Severity.MEDIUM);

    PluginRuleUpdate pluginRuleUpdate2 = new PluginRuleUpdate();
    pluginRuleUpdate2.setNewCleanCodeAttribute(CleanCodeAttribute.EFFICIENT);
    pluginRuleUpdate2.setOldCleanCodeAttribute(CleanCodeAttribute.DISTINCT);
    pluginRuleUpdate2.setRuleUuid("ruleUuid2");

    //testing here detecting the change with 2 the different software qualities
    pluginRuleUpdate2.addNewImpact(SoftwareQuality.SECURITY, Severity.HIGH);
    pluginRuleUpdate2.addOldImpact(SoftwareQuality.RELIABILITY, Severity.MEDIUM);

    underTest.createQprofileChangesForRuleUpdates(dbSession, Set.of(pluginRuleUpdate, pluginRuleUpdate2));

    ArgumentCaptor<RuleChangeDto> captor = ArgumentCaptor.forClass(RuleChangeDto.class);
    verify(ruleChangeDao, times(2)).insert(argThat(dbSession::equals), captor.capture());

    RuleChangeDto firstChange = captor.getAllValues().stream().filter(change -> change.getRuleUuid().equals(RULE_UUID)).findFirst().get();
    RuleChangeDto secondChange = captor.getAllValues().stream().filter(change -> change.getRuleUuid().equals("ruleUuid2")).findFirst().get();

    assertThat(firstChange.getNewCleanCodeAttribute()).isEqualTo(CleanCodeAttribute.CLEAR);
    assertThat(firstChange.getOldCleanCodeAttribute()).isEqualTo(CleanCodeAttribute.TESTED);
    assertThat(firstChange.getRuleUuid()).isEqualTo(RULE_UUID);
    assertThat(firstChange.getRuleImpactChanges()).hasSize(1);
    assertThat(firstChange.getRuleImpactChanges()).extracting(RuleImpactChangeDto::getNewSoftwareQuality,
        RuleImpactChangeDto::getOldSoftwareQuality, RuleImpactChangeDto::getOldSeverity, RuleImpactChangeDto::getNewSeverity)
      .containsExactly(tuple(SoftwareQuality.RELIABILITY, SoftwareQuality.RELIABILITY, Severity.MEDIUM, Severity.LOW));

    assertThat(secondChange.getNewCleanCodeAttribute()).isEqualTo(CleanCodeAttribute.EFFICIENT);
    assertThat(secondChange.getOldCleanCodeAttribute()).isEqualTo(CleanCodeAttribute.DISTINCT);
    assertThat(secondChange.getRuleUuid()).isEqualTo("ruleUuid2");
    assertThat(secondChange.getRuleImpactChanges()).hasSize(1);
    assertThat(secondChange.getRuleImpactChanges()).extracting(RuleImpactChangeDto::getNewSoftwareQuality,
        RuleImpactChangeDto::getOldSoftwareQuality, RuleImpactChangeDto::getOldSeverity, RuleImpactChangeDto::getNewSeverity)
      .containsExactly(tuple(SoftwareQuality.SECURITY, SoftwareQuality.RELIABILITY, Severity.MEDIUM, Severity.HIGH));
  }