jakartaee / data

Data-API
Apache License 2.0
105 stars 29 forks source link

Custom repository method implementations #132

Closed tfeuerba closed 8 months ago

tfeuerba commented 1 year ago

Description

As a:

...I need to be able to:

Provide custom implementations of query methods.

...which enables me to:

Create complex queries, containing for example conditional predicates or custom logic, if it cannot be done with the @Query annotation, query-by-method, or vendor-specific query derivation strategies.

Examples

Proposed Goals

Alternatives

njr-11 commented 1 year ago

This is an excellent idea. Thanks for proposing it. Looking over Spring and Micronaut documentation, both allow you implement default methods on your repository, which seems like a very natural approach to achieving this.

A Micronaut example, (after scrolling down to the third code example),

@Repository
public interface ProductRepository extends CrudRepository<Product, Long>, JpaSpecificationExecutor<Product> {
    @Transactional
    default List<Product> findByName(String name, boolean caseInsensitive, boolean includeBlank) {
        ...
    }

Another Micronaut example, (after scrolling down a number of pages to the large code example block),

@Repository
interface BookRepository extends ReactorCrudRepository<Book, Long> {
    ...

    @Transactional
    default Mono<Void> findByIdAndUpdate(Long id, Consumer<Book> bookConsumer) {
        ...
    }

A Spring example, (after scrolling down a few times),

interface UserRepository extends CrudRepository<User, String>,
                                 QuerydslPredicateExecutor<User>,
                                 QuerydslBinderCustomizer<QUser> {
  @Override
  default void customize(QuerydslBindings bindings, QUser user) {
    ...                                          
  }
}

We would just need to add some language to the Jakarta Data specification stating that you can write default methods on repository interfaces, and the default method will run when invoked on the repository instance. It appears that Spring and Micronaut will already be compatible.

graemerocher commented 1 year ago

Note: Micronaut also supports abstract classes which are useful because you inject other components into the constructor using constructor injection.

otaviojava commented 1 year ago

I love the idea, but please, let's do it after the first release.

njr-11 commented 1 year ago

I love the idea, but please, let's do it after the first release.

I don't see what the advantage would be of waiting until next release. This isn't asking providers to implement new function, just that providers should stay out of the way and not interfere with the default methods that the user includes on the repository interface, so that that user can rely on being able to use their own default methods.

If we don't have the requirement to avoid interfering with the user's default methods from the first release, then it will require a breaking change in a subsequent release of the specification when adding the requirement. I don't see a good case for intentionally putting the specification into a situation like that when it can be easily avoided.

If your comment was about considering abstract classes as repositories, then sure that discussion can be deferred out another release.

otaviojava commented 1 year ago

How about we:

There are a lot of good things to be included, my point is a priority. I mean, if we have this feature without the TCK this is a no-go to Jakarta EE 11.

gavinking commented 8 months ago

This was already done quite a while ago. Please see the preamble of chapter 4 of the spec.

I'm going to close this.