Can entity classes be used as parameters for CrudRepository native queries in Spring Boot 3?

128 views Asked by At

Can entity classes be used as parameters for repository method calls for native queries in Spring Boot 3?

I have some native queries that I have defined in a Spring CrudRepository:

@Repository
interface DataValueRepository extends CrudRepository<DataValue, Long> {


@Query(value=""""
select .......
from data_value dv
            where
                (:neighborhood is null or neighborhood_id = :neighborhood) and
                (:property is null or property_id = :property) and
                (:building is null or building_id = :building) and
                (:household is null or household_id = :household) and
                datetime_local >= :dateLocalFrom and
                datetime_local < :dateLocalToExclusive and
                type in (:types) and
                level = :level
"""
, nativeQuery = true)
List<Object[]> getAggregatedDataValuesWithoutTime(Neighborhood neighborhood, Property property, Building building, Household household, List<String> types, String level, LocalDate dateLocalFrom, LocalDate dateLocalToExclusive);

}

In Spring Boot 2.7, I can send in entity objects such as Neighborhood neighborhood as above, and the :neighborhood in the native query will be substituted by the neighborhood id – or null if the entity is null.

I used to be able to call the repository method like so, where neighborhood, property, building, household are entity objects:

dataValueRepository.getAggregatedDataValuesWithoutTime(neighborhood, property, building, household, dataValueTypes.stream().map(DataValueType::name).toList(), level.name(), period.name(), dateLocalFrom, dateLocalToExclusive);

After upgrading to Spring Boot 3, this no longer works. I get an error

Could not resolve NativeQuery parameter type : `org.hibernate.query.internal.QueryParameterNamedImpl@aaba12d3`

I found a workaround in this post that says that it no longer works to pass entities into the repository methods: https://stackoverflow.com/a/76522587/3150408

So rewriting the repository method to use Integer / Long instead of the entity classes...

List<Object[]> getAggregatedDataValuesWithoutTime(Integer neighborhood, Integer property, Integer building, Long household, List<String> types, String level, String targetPeriod, LocalDate dateLocalFrom, LocalDate dateLocalToExclusive);

...and changing the call of the method to send these types...

dataValueRepository.getAggregatedDataValuesWithoutTime(neighborhood != null ? neighborhood.getId() : null, property != null ? property.getId() : null, building != null ? building.getId() : null, household != null ? household.getId() : null, dataValueTypes.stream().map(DataValueType::name).toList(), level.name(), period.name(), dateLocalFrom, dateLocalToExclusive);

...makes the error go away.

But I think it is quite cumbersome to having to write all the null checks on the entity objects. Is this really the only way of calling these methods in Spring Boot 3? Is there no way to use entities with native queries as before? I can't find any details in any upgrade guides about this change.

0

There are 0 answers