I have migrated from Hibernate 5 to Hibernate 6, and facing an issue while accessing an attribute lazy-loaded via a combination of ForkJoinPool and parallel stream. I have attached a project to reproduce the issue, just launch org.hibernate.bugs.JPAUnitTestCase#test. Basically, my data model is the following:
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Data
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@ToString(onlyExplicitlyIncluded = true)
public class RiskScenario {
@Id
@GeneratedValue
@ToString.Include
private Long id;
@EqualsAndHashCode.Include
@Setter(AccessLevel.PRIVATE)
private UUID uuid = UUID.randomUUID();
@ToString.Include
private String name;
@OneToMany(cascade = ALL, fetch = FetchType.LAZY, mappedBy = "riskScenario", orphanRemoval = true)
private Set<Treatment> treatments = new HashSet<>();
public void addTreatment(Treatment treatment) {
if (treatments == null) {
treatments = new HashSet<>();
}
treatments.add(treatment);
treatment.setRiskScenario(this);
}
}
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Data
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@ToString(onlyExplicitlyIncluded = true)
public class SecurityMeasure {
@Id
@GeneratedValue
@ToString.Include
private Long id;
@EqualsAndHashCode.Include
@Setter(AccessLevel.PRIVATE)
private UUID uuid = UUID.randomUUID();
@ToString.Include
private String name;
@OneToMany(cascade = ALL, fetch = FetchType.LAZY, mappedBy = "securityMeasure", orphanRemoval = true)
private Set<Treatment> treatments = new HashSet<>();
public void addTreatment(Treatment treatment) {
if (treatments == null) {
treatments = new HashSet<>();
}
treatments.add(treatment);
treatment.setSecurityMeasure(this);
}
}
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Data
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@ToString(onlyExplicitlyIncluded = true)
public class Treatment {
@Id
@GeneratedValue
@ToString.Include
private Long id;
@EqualsAndHashCode.Include
@Setter(AccessLevel.PRIVATE)
private UUID uuid = UUID.randomUUID();
@ToString.Include
private String name;
@ManyToOne(cascade = {PERSIST, MERGE}, optional = false)
@JoinColumn(name = "risk_scenario_id")
@ToString.Include
private RiskScenario riskScenario;
@ManyToOne(cascade = {PERSIST, MERGE}, optional = false)
@JoinColumn(name = "security_measure_id")
@ToString.Include
private SecurityMeasure securityMeasure;
}
The test itself that you can find in the project is as followed:
The tricky part is that the error thrown by the test is somehow random:
- Sometimes the test succeeds (but it is quite a rare case)
- Sometimes the test fails with the below exception:
- Sometimes the test fails with the below exception (and this case is the one I managed to reproduce more often):
|