-
Notifications
You must be signed in to change notification settings - Fork 28
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
[Use Case]: multi-item 'select' lists in JDQL #539
Comments
A related idea, that I'm shamelessly stealing from Blaze-Persistence, is the notion of an "entity view". From our perspective, it's a nice way to handle projections with // declare a record type
@Projection(Book.class)
record BookSummary(String title, String isbn,
@Project("length(text)") int length,
@Project("publisher.name") String publisherName) {}
// use it as the return type of a @Find method
@Find
List<BookSummary> bookSummaries(); Note that:
This idea fits in very nicely and consistently with #546. |
For reference, Blaze-Persistence Entity-Views also supports classes and records, but interfaces support multi-inheritance and updatable projections which is why that is preferred. I wanted to propose a new Jakarta EE project at some point to standardize projections, as I believe it has more applicability than just for Jakarta Persistence and Data. The idea is that this new Jakarta project provides annotations and means to introspect the model, as well as create and take apart object instances. |
Sure, I understand that composability is desirable here, but records are composable, just not via inheritance. For modern Java, using records seems more natural and idiomatic. So the trick would be to come up with a nice way to compose them. I have only half-formed ideas about this so far. That said, you're more familiar with all the common usecases here, so it's something we would need to discuss with concrete examples. [P.S. In my head, whenever I write "record", I'm thinking "record or class", which would allow at least single inheritance..]
It seems to me that it makes most sense to begin such discussions/work here, since whatever we come up with certainly has to integrate very cleanly with Jakarta Data. If/when we have something concrete, and realize that it makes more sense in a separate spec, and we see that other specs like Persistence and/or NoSQL are interested in reusing it, then it's straightforward to do a split. We've done that enough times in the past: for example, Persistence started as part of EJB3, Interceptors and even I guess Managed Beans started as part of CDI (then called Web Beans). Similarly, we're currently proposing to split Jakarta Query out of Persistence.
In my head, I was thinking that these projections would probably have a static metamodel, allowing them to be used in dynamic sorting. For example, you might have But when you talk about "introspection" I imagine that you're thinking of something beyond that, something more like a JPA-style Anyway, the point is: my naive inclination would be to design something "small" for Jakarta Data first, and then take a step back and ask if it should be generalized. But of course I really don't yet understand the full picture here, and I reserve the right to backflip on this. :-)
Yes of course. |
My idea for integration is that JPA providers should support accepting the projection type as result type for queries e.g. Projections are IMO also very nice for XML/JSON mapping, where you have one type (e.g. entity) that specifies the canonical model and the projection is just a view onto that. A smart XML/JSON parser can then avoid parsing/materializing certain parts based on the projection expression/paths.
I'm not really a fan of that to be honest as it implies people will have to migrate at some point. I think we will figure out during a discussion that it is worthwhile to have a separate spec for this though.
Yes, that's also something that I more or less did in Blaze-Persistence Entity-Views. I didn't tie that aspect to the metamodel, but instead one can
The main use case is easy integration. If we have this Jakarta Query project and then Jakarta Projections which depends on Jakarta Query, we could expose structured information (like JPA |
Yes, sure, I understand.
Yes, I understand all that. But it seems to me that this automatically Just Works, i.e. that nothing additional needs to be specified to make this possible. Even in Quarkus today, if I do
Well, no, in none of the previous occasions I listed was any migration required.
Nice.
Yes, that's an obvious clean tie-in with #460 (comment). Again, it can be made typesafe.
Yes I agree. |
I'll start off by saying that I'm definitely in favor of adding support for projections. We will need to work out the details. The Projection/Project pattern is nice and has uses beyond Jakarta Data, which is also nice. If that is added in a separate spec, or in a common place (Jakarta Annotations?) to be used by multiple specs, I could see Jakarta Data, as well as Jakarta Persistence, and others, leveraging it. An advantage of that pattern is being able to define the mapping once in a single place. A disadvantage is that you need to be able to own the code of the record/class in order to place the annotations on it, so it rules out projecting to a record type that came from a third-party. We would need to look at advantages and disadvantages more closely, but those are a few that immediately stand out. Starting with the simplest possible scenario where there is direct correspondence between the field names of the record and entity, it would be nice if the user doesn't need to define extra annotations at all, which could be an optimization of the pattern, record BookSummary(String title, String isbn, String description) {}
@Find
List<BookSummary> bookSummaries(); The above pattern (which works because the primary entity type of the repository is known to be When mapping of fields is needed, then we need something more verbose to provide more information. The I already want @Find(_Book.TITLE)
@OrderBy(_Book.TITLE)
List<String> titles(); If we were doing that anyway, it could be natural to allow multiple values, record BookSummary(String title, String isbn, String publisherName) {}
@Find({ _Book.TITLE, _Book.ISBN, _Book.PUBLISHER_NAME})
@OrderBy(_Book.ISBN)
List<BookSummary> bookSummaries(); Trading off the safer usage of limiting oneself to metamodel constants, the above could allow query fragments to be intermixed just as the other model does, record BookSummary(String title, String isbn, int length, String publisherName) {}
static final int BOOK_LENGTH = "length(" + _Book.TEXT + ")";
@Find({ _Book.TITLE, _Book.ISBN, BOOK_LENGTH, _Book.PUBLISHER_NAME})
@OrderBy(_Book.ISBN)
List<BookSummary> bookSummaries(); I'm not saying this alternative pattern is better than the other one. It's another possibility for us to consider, with some slightly different tradeoffs. I'd like to see where the |
As a ...
I need to be able to ...
select multiple fields of my entity in a JDQL
select
list, and have them packaged into some nice typesaferecord
object.Which enables me to ...
handle "subset" or "simplified" views of the entity data, especially useful for externalization.
Additional information
For reference, please see a similar proposal for JPQL: jakartaee/persistence#420
My preferred way to handle this is the following:
The repository method would automatically package the the elements of the
select
list into new instances of the record type. Of course, the "type" of theselect
list must match the signature of the constructor.People sometimes find this useful for creating DTOs.
This would not be for 1.0, but for a future release.
The text was updated successfully, but these errors were encountered: