Skip to content

Projections - query using an interface projection returns all fields if there are collections in the projection #2632

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
MFDEV17 opened this issue Sep 14, 2022 · 2 comments
Labels
status: waiting-for-feedback We need additional information before we can continue status: waiting-for-triage An issue we've not yet triaged

Comments

@MFDEV17
Copy link

MFDEV17 commented Sep 14, 2022

There are several entities in the project, such as User and enum Role, which is used in the User entity as @ElementCollection.

User entity

public class User {
    @Id
    @GeneratedValue(strategy = IDENTITY)
    private Long id;

    @Column(unique = true, nullable = false)
    private String username;

    @Column(unique = true, nullable = false)
    private String email;

    @Column(nullable = false, length = 80)
    private String password;

    @Column(nullable = false)
    private Boolean isActive = false;

    @ElementCollection(fetch = LAZY)
    private Set<Role> roles = new HashSet<>(Set.of(USER));
}

Role enum


public enum Role implements GrantedAuthority {
    USER, ADMIN;
    
    @Override
    public String getAuthority() {
        return name();
    }
}

For the User entity, I created a special projection that includes the following fields, including the role collection:

public interface UserProjection {
    String getUsername();
    String getPassword();
    Set<Role> getRoles();
}

And a JPA repository with a method that finds by username the user using this projection:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

    @EntityGraph(attributePaths = {"roles"})
    Optional<UserProjection> findUserByUsername(String username);
}

When I call this method, I run into the problem that the query contains all fields, including those not specified in the projection:

select
        user0_.id as id1_1_,
        user0_.email as email2_1_,
        user0_.is_active as is_activ3_1_,
        user0_.password as password4_1_,
        user0_.username as username5_1_,
        roles1_.users_id as users_id1_2_0__,
        roles1_.roles as roles2_2_0__ 
    from
        users user0_ 
    left outer join
        users_roles roles1_ 
            on user0_.id=roles1_.users_id 
    where
        user0_.username=?

But if I remove the collection from the projection, the query starts working correctly:

select
        user0_.username as col_0_0_,
        user0_.password as col_1_0_ 
    from
        users user0_ 
    where
        user0_.username=?

Can you please tell me what could be the problem? I'm not very experienced in using Spring Data JPA, and I can't figure out if this is a bug or some implementation feature that I missed. I couldn't find any answers in the documentation. Thanks

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Sep 14, 2022
@schauder
Copy link
Contributor

We try to limit fields selected as much as possible for interface projections.
But when collections are involved there is no way AFAIK to get the collections instantiated without querying for actual entities, which in turn will select all the fields.

I don't see a way how we can improve on this without reimplementing the mapping logic of the JPA implementation at hand, and I don't think we want to get into that.

@mp911de mp911de added the status: waiting-for-feedback We need additional information before we can continue label Sep 15, 2022
@MFDEV17
Copy link
Author

MFDEV17 commented Sep 15, 2022

Gotcha. Thanks for the feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: waiting-for-feedback We need additional information before we can continue status: waiting-for-triage An issue we've not yet triaged
Projects
None yet
Development

No branches or pull requests

4 participants