micronaut-projects / micronaut-data

Ahead of Time Data Repositories
Apache License 2.0
465 stars 197 forks source link

Allow text between introducing keyword and By in query method names #1326

Open christopher-mohr opened 2 years ago

christopher-mohr commented 2 years ago

Feature description

In some situations it would be convenient to be able to use descriptive text between the introducing keyword (such as find) and By in query method names as it is already possible in Spring Data.

Description from the Spring Data documentation:

Parsing query method names is divided into subject and predicate. The first part (find…By, exists…By) defines the subject of the query, the second part forms the predicate. The introducing clause (subject) can contain further expressions. Any text between find (or other introducing keywords) and By is considered to be descriptive unless using one of the result-limiting keywords such as a Distinct to set a distinct flag on the query to be created or Top/First to limit query results.

This would allow to use more expressive method names without affecting query derivation.

One use case would be if multiple methods that use the same property only differ by additional annotations, e.g.:

findById(String id)

@Join(value = "someEntity", type = Join.Type.LEFT_FETCH)
findWithSomeEntityById(String Id)
rawilder commented 2 years ago

Another use case is dto projection right now only works with repository methods implemented by micronaut-data without @Query.

interface ThingRepository: PageableRepository<Thing, Int> {
    // normal, works
    fun findById(id: Int): Page<Thing>

    // cannot duplicate method name and function name doesn't indicate
    // that it's a subset of thing
    fun findById(id: Int): Page<ThingSubsetDto>

    // this can't be implemented
    fun findSubsetDtoById(): Page<ThingSubsetDto>

    // the dto projection doesn't work with @Query
    @Query("from Thing t where t.id = :id")
    fun findSubsetDtoById(id: Int): Page<ThingSubsetDto>
}
PiotrBaczkowski commented 2 years ago

Is it planned to be developed? Its much needed feature

dstepanov commented 2 years ago

In Micronaut Data everything between find and by is a projection and you will get a compilation error if you are trying to reference something that doesn't exist. You can write String findNameById to get only the name property from the entity. This kind of construction Spring Data doesn't support.

Maybe we can support suffix Returning to allow findNameByIdReturningCustom.

dstepanov commented 2 years ago

@rawilder Can you please create a sample project showing cases that don't work

rawilder commented 2 years ago

github: https://github.com/rawilder/mn-data-dto-demo query dto method: https://github.com/rawilder/mn-data-dto-demo/blob/master/src/main/kotlin/dev/awilder/TestEntityRepo.kt#L22 failing test: https://github.com/rawilder/mn-data-dto-demo/blob/master/src/test/kotlin/dev/awilder/MnDataDtoDemoTest.kt#L26

PiotrBaczkowski commented 1 year ago

In Micronaut Data everything between find and by is a projection and you will get a compilation error if you are trying to reference something that doesn't exist. You can write String findNameById to get only the name property from the entity. This kind of construction Spring Data doesn't support.

Maybe we can support suffix Returning to allow findNameByIdReturningCustom.

it isn't only about DTO, it's also about specifying which JOINs do you need in exact scenerio, right now repository methods always have to go with the most wide joining strategy and join relations not needed in given case but needed in another case.