Specifying a Spring Projection

Spring Data JPA makes it easy to interact with JPA data sources inside a Spring application.  Projections are a mechanism for returning a subset of data from a JPA repository. In this post I’ll discuss a unique way of specifying the desired projection when invoking repository methods.

Consider the following repository:

public interface UserRepository extends CrudRepository {}

A User entity is defined as:

public Long getId();
public String getUsername();
public String getPasswordHint();
public String getFullName();
public String getBio();

Assume we need to work with two different views of the user inside our application:  an in-network view consisting of id, username, fullName, bio and an out-of-network view consisting of id, username, fullName.

We’ll create two projections; these are simply interfaces that expose the desired property getters, e.g.

public interface ExternalUserView {
    public Long getId();
    public String getUsername();
    public String getFullName();
}

Projections are often utilized by adding new interface methods to the repository, e.g.

List<InternalUserView> finalAllInternalUsersBy();
List<ExternalUserView> finalAllExternalUsersBy();
...

However, this approach can lead to method clutter if you have several projections and/or custom query methods.  An improved approach involves passing the desired projection as a parameter:

<T> List<T> findAllBy(Class<T> clazz);
<T> Optional<T> findById(Long id, Class<T> clazz);

The projection can now be specified when calling a repository method, e.g.

List<InternalUserView> users = repo.findAllBy(InternalUserView.class);

If you’re making significant use of projections, consider using this approach to keep your code clean and terse. A working example is available here.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s