jakartaee / jakartaee/persistence

Safe-navigation operators (`myentity?.myToOne`) for implicit left joins

Open
#697 6 comments 2 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.