I have the following entity structure (the DB is given):
@Data
@Entity
public class Report {
@EmbeddedId
private ReportId id;
private int numberOne;
private int numberTwo;
}
Within my reports I need the complete site. But it might be deleted (no foreign key constraint).
@Data
@Entity
public class Site {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String place;
private String name;
}
For every site and day there is a report. I am not interested in reports from deleted sites.
@Embeddable
@Data
public class ReportId implements Serializable {
@NotFound(action = NotFoundAction.IGNORE) //without this we get EntityNotFoundException for deleted sites
@Fetch(FetchMode.JOIN)
@OneToOne
@JoinColumn(name = "site_id", referencedColumnName = "id")
private Site site;
@Column(name = "day")
private LocalDate date;
}
What I want is that a "selectAll()" only returns reports that are linked to existing sites (lookup by site id is returning not null).
As you see I already tried @NotFound(action = NotFoundAction.IGNORE) but this creates entries with site = null.
I think what I need is a left outer join of site but it seems @Fetch(FetchMode.JOIN) is just ignored - I still see 2 selects per report (first selecting the report 2nd fetching the site by id).
I also tried to put these annotations on to @EmbeddedId column in Report but this is not working (@NotFound is also ignored there).
Is there a way to ignore all reports without an existing site? - I don't want to write the queries manually. I want to use Spring Data repository methods like - findAll().
Actually under the hood when you run the findAll() method spring data jpa perform the following jpa query:
select r from Report r
But as it stated in the hibernate documentation:
The reason why we are not using a JPQL query to fetch multiple entities is because the
FetchMode.JOINstrategy would be overridden by the query fetching directive.To fetch multiple relationships with a JPQL query, the
JOIN FETCHdirective must be used instead.Therefore,
FetchMode.JOINis useful for when entities are fetched directly, via their identifier or natural-id.Also, the
FetchMode.JOINacts as aFetchType.EAGERstrategy. Even if we mark the association asFetchType.LAZY, theFetchMode.JOINwill load the association eagerly.
So, it looks like you will not be able to achieve that you want without a separate query.
This is a known Hibernate issue. Just don't define associations in the embedded id type. You can define the basic column attributes in the embedded id type and the associations in the main entity type by using @JoinColumn(insertable = false, updatable = false)
UPDATE: Use this:
@Embeddable
@Data
public class ReportId implements Serializable {
@Column(name = "site_id", referencedColumnName = "id")
private Integer siteId;
@Column(name = "day")
private LocalDate date;
}
@Data
@Entity
public class Report {
@EmbeddedId
private ReportId id;
@Fetch(FetchMode.JOIN)
@OneToOne
@Column(name = "site_id", referencedColumnName = "id", insertable = false, updatable = false)
private Site site;
private int numberOne;
private int numberTwo;
}
I can't find the issue right now, you can open a new one if you want.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With