Skip to content

SQL query not optimized when using Projection with a Specification (FetchableFluentQuery)Β #2721

@gonzalad

Description

@gonzalad

Hello,

Summary

Atm, using projection with specifications doesn't change the generated SQL query, the JPA entity is still loaded under the hood.

Could we expect query optimization in the future when using Projections with Specifications ? (limiting the fields to be loaded to those of the projection interface/class ?)

Detailed issue

I just tried SB 3.0 Projection support with Specifications:

    @Test
    void testProjectionBySpecification() {
        repository.save(new Customer("victor"));

        List<CustomerProjectionInterfaceBased> result = repository.findBy(
                customerHasFirstnameLike("v"),
                q -> q.as(CustomerProjectionInterfaceBased.class).all()
        );

        assertThat(result).hasSize(1);
    }

    private interface CustomerProjectionInterfaceBased {
        String getFirstname();
    }

This works nicely, bu when I look at the sql, I see:

select c1_0.id,c1_0.firstname,c1_0.lastname from customer c1_0 where cast(c1_0.firstname as varchar(2147483647)) like ?

I would have expected the SQL to fetch only the properties from the projection, i.e.:

select c1_0.firstname from customer c1_0 where cast(c1_0.firstname as varchar(2147483647)) like ?

Even if I use project(<property>):

        List<CustomerProjectionInterfaceBased> result = repository.findBy(
                customerHasFirstnameLike("v"),
                q -> q.as(CustomerProjectionInterfaceBased.class)
                        .project("firstname")
                        .all()
        );

I still get the same sql.

Looking at the source code, I see in FetchableFluentQueryBySpecification:

The project(property) method updates the properties attribute. This attribute is only used to set the fetchgraph

if (!properties.isEmpty()) {
  query.setHint(EntityGraphFactory.HINT, EntityGraphFactory.create(entityManager, entityType, properties));
}

The as(Class) method is used after executing the jpa query to convert the jpa entity to the projection type, hence this one doesn't change the sql query generation behaviour atm.

So, to optimize the generated query, the only way I found atm would be to rely on project(String), activate bytecode enhacement and annotate each basic attribute with @Basic(fetch=LAZY).

But setting @basic(fetch=LAZY) seems to me to be too much hassle because it impacts all the queries I already have in my application.

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: supersededAn issue that has been superseded by another

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions