I am trying to use Spring JPA's projection to filter out unnecessary data from query result. However, I have multiple projections that will need to be used on the same interface method.
The problem is, I am trying to query data from the same method with a different returning object but java doesn't allowed this.
The query are auto generated by JPA based on method name, so I cannot make changes to method name.
Is there a alternative, other than creating a new interface, since I think it's a hassle and unnecessary
here is a sample code, of what I am trying to do.
Auto-Generated Query
public interface UserRepository extends CrudRepository<UserAccount, Long> {
AuthenticateProjection getByUsername(String username);
UserDetailsProjection getByUsername(String username);
}
Projections
public interface AuthenticateProjection {
@Value("#{target.username}")
String getUsername();
@Value("#{target.credentail.token}")
String getHashPassword();
}
public interface UserDetailsProjection {
@Value("#{target.username}")
String getUsername();
@Value("#{target.firstname}")
String getFirstName();
@Value("#{target.lastname}")
String getLastName();
}
So I've managed to figure out how to use multiple projections with a single query.
<T> T getByUsername(String username, Class<T> projection)
This allows the method caller to specified the type of projection to be applied to the query.
To further improve this so it is less prone to error, I made a blank interface that the projection will have to extend in order to be able to insert class into the parameter.
public interface JPAProjection {
}
public interface UserRepository extends CrudRepository<UserAccount, Long> {
<T extends JPAProjection > T getByUsername(String username, Class<? extends JPAProjection> projection);
}
Projection Interface
public interface UserDetailsProjection extends JPAProjection{
@Value("#{target.username}")
String getUsername();
@Value("#{target.firstname}")
String getFirstname();
@Value("#{target.lastname}")
String getLastname();
}
Then I can call the query method by
getByUsername("...", UserDetailsProjection.class)
Just add something between get (or e.g. find) and By starting with an upper case character. It is ignored in the query generation.
public interface UserRepository extends CrudRepository<UserAccount, Long> {
AuthenticateProjection getByUsername(String username);
UserDetailsProjection getAnotherByUsername(String username);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With