baao baao - 3 months ago 36
Java Question

Exclude column from resultset in controller | Spring data jpa

I have a Users Entity:

public class SpringUsers implements Serializable {
private String password;
// other fields omitted
@Basic
@Column(name = "password")
public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}
}


And its repository:

public interface SpringUsersRepository extends CrudRepository<SpringUsers, Integer> {
SpringUsers findByUsername(String username);
List<SpringUsers> findByUserId(Integer userId);
}


And I have a controller method that should get a list of all registered users with the same userId (is internally used) as the currently authenticated user:

public List<SpringUsers> getRegisteredUsers() {
CustomUserDetails authenticatedUserDetails = getCustomUserDetails();
List<SpringUsers> registered = springUsersRepository.findByUserId(
authenticatedUserDetails.getUserMyId());
return registered.stream().map(v -> {
v.setPassword(null);
return v;
}).collect(Collectors.toList());
}


I don't want to pass the password (even though it's encrypted) to the frontend - so I stream through the users and set the password to null, as you can see above.

However, I'm wondering if there isn't a possibility to just not include the users' password in the query result in the first place?




Version Info:

Spring boot 1.4.0 &
Hibernate 5.0.9.Final

Answer

You can use @Query to selectively include some fields:

// Include all fields you wanna query for using u.x syntax
// AFAIK there is no exclusion syntatic sugar
@Query("select u.id, u.username from SpringUsers u where u.id = ?1")
List<SpringUsers> findByUserId(Integer userId);

Also you can use Projections. First define the projection by introducing a projection interface:

interface NoPasswordUser {
    Long getId();
    String getUsername();
    // Do not include getPassword();
}

Then use it in your repository:

public interface SpringUsersRepository extends CrudRepository<SpringUsers, Integer> {
    NoPasswordUser findByUsername(String username);
    List<NoPasswordUser> findByUserId(Integer userId);
}

Anyway, It's better to not expose your entities through a REST or any remote interface. You can use DTOs for that matter, this post may be useful in this area.

Comments