Skip to content

Java: Views and Projections #1916

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open

Java: Views and Projections #1916

wants to merge 10 commits into from

Conversation

MattSchur
Copy link
Contributor

@MattSchur MattSchur commented Jun 11, 2025

Introduces "Views and Projections" section with

  • Runtime Views
  • Write through Views

and documents some rules for write via path expressions in views.

Also shortens some headers to improve the readability in the navigation bar.

@MattSchur MattSchur requested a review from smahati as a code owner June 11, 2025 16:17
@MattSchur MattSchur changed the title Java: Write through Views Java: Views and Projections Jun 12, 2025
@MattSchur MattSchur requested a review from vmikhailenko June 12, 2025 15:03
::: warning Limitations of `resolve` mode
Using associations introduced by the view (mixins), as well as complex draft queries, and [draft-enabling](../fiori-drafts#reading-drafts) runtime views are not supported in *resolve* mode.
:::

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also add that runtime views are not lockable. See https://cap.cloud.sap/docs/java/working-with-cql/query-api#write-lock

Copy link
Contributor Author

@MattSchur MattSchur Jun 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pessimistic locking is possible if the runtime view can be resolved or the view (generated CTE) fulfills the conditions mentioned in locking, which should be the case since we don't support union, join and aggregations in runtime views. It locks the underlying table rows.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On HANA? Wow.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, HANA seems to not support locks via CTEs, so only the resolve mode works. I'll add a note.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should fix this? E.g. use different mode for queries with locks? They are usually very simple and should resolve to the baseline entity 1:1.

@vmikhailenko
Copy link
Contributor

Overall, LGTM. It is nice that we explain this stuff.

@MattSchur MattSchur requested a review from vmikhailenko June 16, 2025 13:39
- The projection includes all elements with a `not null` constraint, unless they have a default value.
- The projection must not include calculated fields when running queries against a remote OData service.
- The projection must not include [path expressions](../../cds/cql#path-expressions) using to-many associations.
::: tip Avoid mixin compositions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a red box? If this leads to a data loss or garbage being left, then it is nasty.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be sufficiently explain later. Why mention it here?

WHERE A.NAME = ?
```

::: tip CAP Java 3.10
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we really document outdated stuff?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should mention this, since 3.10 is the LTS release.

If you define runtime views on [draft-enabled](../fiori-drafts#reading-drafts) entities and want to run draft specific queries on these views, set the *cds.drafts.persistence* configuration to `split` and run the queries through the [Draft Service](../fiori-drafts#draft-service) or [Application Service](../cqn-services/application-services#application-services). The [Persistence Service](../cqn-services/persistence-services) only works for non-draft specific queries.

::: warning Avoid draft-enabling runtime views
[Draft-enabling](../fiori-drafts#reading-drafts) runtime views is only supported in *cte* mode. The cds-compiler creates a corresponding draft persistence table for the view and a database schema update is required each time the runtime view is changed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this whole chapter should sound like: if you draft-enable runtime views make sure that CTE mode is used and draft persistence is in split mode, you should use draft service for queries to them (which is general requirement) and your view is updatable. Like this whole chapter is a warning without the yellow box.

cds-compiler

CDS Compiler?

entity Order as projection on bookshop.Order excluding { status };
entity Header as projection on bookshop.OrderHeader { key ID, address.country as country };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This model should have reference to its base model. It is not clear that header is a composition.

- [Deep write](./query-execution#deep-insert-upsert) via (aliased) compositions (*items*) is supported if there are corresponding compositions in the underlying entity definition. Deep write via compositions that are only defined in the view (mixins) is not supported and the data for such mixin compositions is ignored.

::: warning Path Expressions in Views
Path expressions navigating *associations* (e.g. *header.customer.name*) are [not writable](#cascading-over-associations) by default. To avoid issues on write, annotate them with [@readonly](../../guides/providing-services#readonly).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that warning is not necessary here. We just list instructions: the one about mixins (maybe also add a reference to some definition of this concept) is as important as the paths inside associations not being writable.

Except the keys, right?

- The projection includes all elements with a `not null` constraint, unless they have a default value.
- The projection must not include calculated fields when running queries against a remote OData service.
- The projection must not include [path expressions](../../cds/cql#path-expressions) using to-many associations.
::: tip Avoid mixin compositions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be sufficiently explain later. Why mention it here?


The runtime _resolves_ the view definition to the underlying persistence entities and executes the query directly against the corresponding tables.

```sql
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The more I read this (especially these references later in chapters on modifications and deletions), the more I feel that we are to vague about what this resolve mode actually does.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should not reference this mode later for modifications. This is actually very hard to match the statements:

  • this mode does not support draft-enabled entities (for read, but this never clearly stated)
  • the updates write through view using similar technique.
  • but drafts somehow function? What exactly will work?


### Write through Views { #updatable-views }

You can run [Insert](./query-api#insert), [Upsert](./query-api#upsert), and [Update](./query-api#update) statements on CDS views. The CAP Java runtime attempts to resolve these to the underlying entity definitions—similar to the runtime view [resolve mode](query-execution#resolve-mode) for queries.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vmikhailenko
Copy link
Contributor

Maybe we should try to structure this differently:

There are views in CDS and they work fine (unless the fact that they trigger database migrations) and they also can be writable. If they are writabe, one need to take into account this and that.

They can also be draft-enabled and this implies that they are writable and they must be read and written through the draft service.

Then, there is a special kind of views - runtime views. In addition to the limitations for writable views, one needs to take into account more things e.g. with drafts and limited write support.

This might help to avoid cross references and repeatable warnings. What do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants