Conversation
|
|
|
||
| public static void main(String[] args) { | ||
| int[] sizes = args.length > 0 ? parseSizes(args[0]) : new int[] {10, 100, 1000}; | ||
| int parentRows = args.length > 1 ? Integer.parseInt(args[1]) : DEFAULT_PARENT_ROWS; |
| String[] parts = arg.split(","); | ||
| int[] sizes = new int[parts.length]; | ||
| for (int i = 0; i < parts.length; i++) { | ||
| sizes[i] = Integer.parseInt(parts[i].trim()); |
| return reference; | ||
| } | ||
|
|
||
| public Set<OrderItem> getItems() { |
| return reference; | ||
| } | ||
|
|
||
| public Set<OrderItem> getItems() { |
This was referenced Aug 7, 2026
Closed
Closed
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Supersedes PRs #122, #125, #155, #325 and resolves #98, #116, #118
Context
Four PRs have proposed this rule since April 2023 (#122, #125, #155, #325). None could be merged:
three of them target the old
java-plugin/layout that no longer exists in this repository, andthey use four different rule keys (
EC80,CRJVM205,EC_CRJVM205,EC205). On review, the rulealready exists inside SonarQube as the built-in rule
java:S6904. This PR does not add a newspecification: it keeps the
CRJVM205entry inRULES.md, updates it to point at the built-inrule, and preserves the work already done as supporting analysis rather than letting it go to
waste — see Measured impact below.
What this PR contains
RULES.md— updates theCRJVM205row: instead of a new rule entry, it now states the rulealready exists inside SonarQube as the built-in rule
java:S6904, with the Reference/Validationlink pointing at this PR.
CHANGELOG.md— entry under[Unreleased]/Added: "Add complete analysis for FetchType issuefor Java (sonarqube built-in rule S6904)".
src/main/rules/S6904/java/S6904.asciidoc— documentation explaining why this isn't a newGCIxxxrule, plus the standard "why is this an issue," compliant/noncompliant examples,exceptions and resources sections, and a pointer to the full measurement analysis.
src/main/rules/S6904/java/analysis/— the two-level measurement harness (JPA/Hibernatefunctional cost, then EnergyTracer hardware energy measurement) and two independent measurement
campaigns, added to answer the impact question the four superseded PRs left open. See
Measured impact below.
Scope decision
The rule targets collection associations only (
@OneToMany,@ManyToMany) and only whenfetch = FetchType.EAGERis set explicitly. Omittingfetchon those annotations is compliant,since
LAZYis already the JPA default — PR #155 reported those cases, which would have producedfalse positives on the most common mapping in the domain.
Single-valued associations (
@ManyToOne,@OneToOne) are explicitly out of scope: their costprofile is different and their real impact belongs to the N+1 selects problem (
CRJVM206).Measured impact
None of the four superseded PRs provided any measurement of the actual cost — that gap is what
stalled the core-team discussion since April 2023. Two independent campaigns close
it, using a real Hibernate stack for functional cost and EnergyTracer's hardware counters
(Apple Silicon CPU/GPU/DRAM) for energy, 900 runs per variant per size across 30 measurement
phases.
Functional cost (Hibernate 6.4.4 + H2, single run per size):
The statement count never changes — Hibernate resolves the eager collection with a join, so this
is a payload/hydration cost, confirming the N+1 exclusion in the scope decision above rather than
overlapping with it.
Energy cost (two campaigns, six distinct collection sizes from 10 to 1000; three of them,
10/100/1000, measured independently in both):
Every one of the 30 measurement phases at every size points the same way, at both hardware
components (CPU, DRAM) and wall time, with strictly disjoint EAGER/LAZY distributions. The
relative overhead is already large at the smallest size tested (10 elements) and climbs to 90%+
at 1000. The second campaign also located a genuine, honestly-disclosed anomaly in the
fine-grained scaling curve around 50–100 elements, which does not change this conclusion (see
campaign 2's document, §4–§5).
Reproducibility across the two independent measurement sessions (different days) is strong: the
relative overhead never moved by more than 0.6 percentage points at the three sizes tested in
both campaigns, even though absolute joule readings drifted by up to 16% between sessions —
which is why every figure above is a relative, paired comparison rather than a raw energy total.
Full detail, including the honest caveats (bimodal phases, the
CONTEXT_SIZEconfound, why thetool's own p-values are not cited, the modest absolute yearly saving):
campaign1-interpretation.mdand
campaign2-interpretation.mdundersrc/main/rules/S6904/java/analysis/level2-energytracer/.Credits
@ManyToMany(EAGER)example, real-project validationormtag