spring-projects / spring-projects/spring-data-relational
Derived queries on snake_case mapped columns trigger repeated PropertyReferenceException lookups and create avoidable overhead
@schauder is already working on this.
Since Aug 3, 2026.
- Dominant language
- Java
- Stars
- 827
- Forks
- 394
- PR merge metrics
- No merged PRs in 30d
Description
Environment
- Java 25
- Spring Boot 3.5.x
- Spring Data R2DBC 3.5.x
- Oracle Database
Description
When an entity uses camelCase Java properties mapped to snake_case database columns, derived query execution appears to perform repeated failed property lookups for each referenced column. These failures are handled internally and discarded, but they still incur exception construction and stack-trace overhead.
For example, a derived method such as findByCustomerIdIn(...) on an entity with a customerId property and a customer_id column appears to cause the query mapper to attempt resolving customer_id as a Java property, fail with PropertyReferenceException, and then fall back to treating it as a raw column name.
Impact
This creates avoidable overhead on every derived query execution. In profiling, a significant amount of CPU time is spent inside exception creation and stack-trace generation, even though the exception is expected and immediately handled.
Observed behavior
- Each relevant WHERE-clause column appears to trigger a failed property-resolution attempt.
- The exception is caught internally and used as control flow.
- The behavior is correct functionally, but expensive at runtime.
Expected behavior
The query mapper should first check whether the input matches a known persistent property before attempting exception-based resolution, avoiding exception creation for raw column names.
Why @Column does not help
The lookup appears to happen before @Column metadata is consulted, so annotating the field does not prevent the failed property-resolution attempt.
Suggested improvement
Prefer a non-exception-based check for known persistent properties before calling PropertyPath.from(...), or otherwise cache/short-circuit the raw-column case.
Workaround
Using explicit @Query methods avoids this path.
Minimal example
@Table("orders")
public class Order {
@Id
private Long orderId;
private Long customerId;
private String status;
}
public interface OrderRepository extends ReactiveCrudRepository<Order, Long> {
Flux<Order> findByCustomerIdIn(List<Long> customerIds);
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.