Skip to content

Add @NativeQuery annotation#1409

Draft
yrodiere wants to merge 2 commits intojakartaee:mainfrom
yrodiere:native
Draft

Add @NativeQuery annotation#1409
yrodiere wants to merge 2 commits intojakartaee:mainfrom
yrodiere:native

Conversation

@yrodiere
Copy link
Copy Markdown

Opening as a draft to gauge the appeal... I mostly focused on javadoc for now and have not looked in details at the spec. I will push an update to address that later.


Jakarta Data has @Query, Jakarta Persistence has @StaticQuery.

Jakarta Persistence also has @StaticNativeQuery, but Jakarta Data has... nothing?

This is an attempt at filling the gap, so that applications can rely on Jakarta Data to write (some) native queries, and more importantly (for me) can use an annotation with a simple, intuitive name to do so.

Note this is an entirely optional feature, and the syntax of native queries is implementation-dependent. As such, I do not know how to add TCK tests.

cc @gavinking

Because this is contradicted by the javadoc of @StaticNativeQuery:

>  * <p> A method parameter type agrees with a query parameter type if it is
>  * a type that could be assigned to the corresponding query parameter by
>  * passing an instance of the type to {@code setParameter()}. In making
>  * this determination, method parameters are correlated with query parameters
>  * by position or by name, depending on whether the query uses positional or
>  * named parameters.

https://github.com/jakartaee/persistence/blob/aa6d88bd97711d593ab9b5f18def6a6129912b79/api/src/main/java/jakarta/persistence/query/StaticNativeQuery.java#L70-L75
@njr-11
Copy link
Copy Markdown
Member

njr-11 commented Mar 24, 2026

@yrodiere - You did some very nice work writing up the Javadoc for this.

There was an issue about native queries in Jakarta Data opened and discussed last September. It was closed last month with the solution being that @StaticNativeQuery from Jakarta Persistence (which can be used on Jakarta Data repositories) now provides the solution for SQL, and Otavio indicated that for NoSQL it would be preferable for the respective providers to supply their own custom annotations.

@otaviojava
Copy link
Copy Markdown
Contributor

There are a couple of problems with including an annotation to broad, I mean, it could accept anything.

  1. How to define TCK to native test to any database?
  2. Our goal is not to replace any specification; in this case, it would be better to have specialization annotations as we have with Jakarta Persistence.

For sure, we can open a discussion and review, if it is a good time to have it.

@yrodiere
Copy link
Copy Markdown
Author

yrodiere commented Mar 25, 2026

Personally, my main reason for wanting this annotation is that I want to ship Jakarta Data as part of a framework (Quarkus) with clear, simple documentation, especially for new users. And the current situation makes that hard.

If I want to document to these users one recommended way of doing JPQL and native queries, I have a choice between:

  1. Leaving out @Query altogether, sticking to JPA-specific annotations. The "static" prefix in that case makes it quite weird (especially since, with a Restriction, it's not actually a static query).
interface MyRepo {

    @StaticQuery("where name = :name order by name")
    List<Product> findByName(String name, Restriction<Product> restriction); 

    @StaticNativeQuery("select book.title, book.isbn from book where title :title")
    List<BookRecord> findBooks(String title);

}
  1. Mixing @Query with @StaticNativeQuery. Now we have quite some inconsistency in naming, and the "static" prefix becomes even more surprising.
interface MyRepo {

    @Query("where name = :name order by name")
    List<Product> findByName(String name, Restriction<Product> restriction); 

    @StaticNativeQuery("select book.title, book.isbn from book where title :title")
    List<BookRecord> findBooks(String title);

}
  1. Mixing @Query with implementation-specific annotations, e.g. Hibernate's @SQL.
interface MyRepo {

    @Query("where name = :name order by name")
    List<Product> findByName(String name, Restriction<Productok> restriction); 

    @SQL("select book.title, book.isbn from book where title :title")
    List<BookRecord> findBooks(String title);

}

I understand the "static" prefix in the JPA annotations does make sense because it's about adding the query specs to the metamodel more than about the Jakarta Data integration, and I also understand, having talked with Gavin, that it's unlikely to change.

If we don't want to add @NativeQuery in Jakarta Data, then I think that option 3 is the cleanest option we have in Quarkus, and we'll need to give up on standards for the native part.

I find it a bit of a shame given we do have an almost-perfect standard for this (we just lack an annotation with loose semantics!), but I understand that might be the pragmatic solution.

@njr-11
Copy link
Copy Markdown
Member

njr-11 commented Mar 25, 2026

  1. Leaving out @Query altogether, sticking to JPA-specific annotations. The "static" prefix in that case makes it quite weird (especially since, with a Restriction, it's not actually a static query).
interface MyRepo {

    @StaticQuery("where name = :name order by name")
    List<Product> findByName(String name, Restriction<Book> restriction); 

You have an excellent point here. The repository method is not performing a static query at all when Restriction, or OrderBy, or cursor-based pagination cause additional constraints and ordering to be appended to it. That said, the problem is on the Jakarta Persistence side, not Jakarta Data. Fortunately, as far as I am aware, all of the names with Static in them are new to Persistence 4.0, which has the same release schedule as Data 1.1, so the Persistence spec can still make improvements to its names. The Jakarta Persistence spec does explicitly document these annotations for use with Jakarta Data as well as Persistence. One idea that comes to mind is to change:

@StaticQuery(jpql) --> JPQLQuery(jpql)
and
@StaticNativeQuery(sql) --> NativeQuery(sql)

Something like the above would result in more concise, but still meaningful, names. Others on the Jakarta Persistence spec might have even better ideas.

Would you be willing to open an issue on the Jakarta Persistence spec for this?

@yrodiere
Copy link
Copy Markdown
Author

Would you be willing to open an issue on the Jakarta Persistence spec for this?

Done here: jakartaee/persistence#991

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.

3 participants