jakartaee / jakartaee/persistence
Safe-navigation operators (`myentity?.myToOne`) for implicit left joins
- Dominant language
- Java
- Stars
- 267
- Forks
- 78
- Avg merge
- 1d 6h
- Merged PRs (30d)
- 13
Description
## Problem statement
The JPA spec defines the navigation operator (`.`) in JPQL queries as [yielding inner joins](https://jakarta.ee/specifications/persistence/3.2/jakarta-persistence-spec-3.2#a4792) when it triggers implicit joins:
> Path expression navigability is composed using “inner join” semantics. That is, if the value of a non-terminal field in the path expression is null, the path is considered to have no value, and does not participate in the determination of the result.
But there is a class of queries where a *left join* would be more convenient, e.g. here if `documentType` is optional, we have to write this:
```sql
SELECT document.id, documentType.name
FROM Document document LEFT JOIN document.documentType documentType
```
... in order to get this SQL:
```sql
SELECT d.id, dt.name
FROM document d LEFT JOIN document_type dt ON d.document_type_id = dt.id
```
Whereas we'd love to be able to write just this:
```sql
SELECT document.id, documentType.name -- Incorrect, this leads to an inner join
FROM Document document
```
... but obviously this is incorrect and will yield this SQL:
```
SELECT d.id, dt.name
FROM document d INNER JOIN document_type dt ON d.document_type_id = dt.id
```
## Proposal
This behavior is what it is, but changing it [would be challenging or would involve workarounds (hints)](https://www.eclipse.org/lists/jpa-dev/msg00077.html), so it'll very likely stay that way.
We could, however, offer an alternative to the navigation operator (`.`) which would yield left joins instead of inner joins. This behavior is, in a way, similar to the safe-navigation operator (`?.`) used in various programming languages, so that operator would be a decent choice.
So we would be able to write this:
```sql
SELECT document.id, document?.documentType?.name
FROM Document document
```
And get the SQL we want, with an implicit left join:
```sql
SELECT d.id, dt.name
FROM document d LEFT JOIN document_type dt ON d.document_type_id = dt.id
```
In some extensions to JPQL, e.g [in Hibernate](https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#hql-select), this could even be shortened to just `SELECT document.id, document?.documentType?.name`, without a `FROM` clause due to that clause being inferred from context -- but this is obviously out of scope for this issue.
This could remove a lot of verbosity in queries that -- all things considered -- are rather simple in their objectives, but get weighted down by the need for explicit joins.
For example this JPQL:
```sql
SELECT document.id, document.title, documentType.name, author.name, manager.name, folder.name
FROM Document document
LEFT JOIN document.documentType documentType
LEFT JOIN document.author author
LEFT JOIN author.manager manager
LEFT JOIN document.folder folder
```
... would become simply:
```sql
SELECT document.id, document.title, document?.documentType?.name,
document?.author?.name, document?.author?.manager?.name, document?.folder?.name
FROM Document document
```
... or even (HQL with context-inferred `FROM` clause):
```sql
SELECT document.id, document.title, document?.documentType?.name,
document?.author?.name, document?.author?.manager?.name, document?.folder?.name
```
## Further considerations
1. While the safe navigation operator can be assigned a clear, intuitive meaning for associations, we would need to make an arbitrary choice for other attributes.
For example, `name` being mapped to a `varchar` column, should we mandate that developers write `document?.documentType?.name`, or `document?.documentType.name`? Should we allow both?
2. If JPQL defines an `[]` operator, it could make sense to define a "safe" version there too, i.e. `?[]`. That is, depending on whether this operator implies inner joins (??) and whether we decide to allow `?.` on non-association attribute access.
Contributor guide
Research direction
Start with the linked JPA specification section on path-expression navigability and compare its inner-join semantics with the issue's implicit left-join examples. Define the behavior of `?.` for associations and non-association attributes, and decide whether a safe `[]` operator is also in scope; the proposal is complete when those semantics and their compatibility implications are resolved.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- database
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100