从控制器的结果集中排除列 |弹簧数据 jpa
Posted
技术标签:
【中文标题】从控制器的结果集中排除列 |弹簧数据 jpa【英文标题】:Exclude column from resultset in controller | Spring data jpa 【发布时间】:2017-01-10 16:52:23 【问题描述】:我有一个用户实体:
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;
及其存储库:
public interface SpringUsersRepository extends CrudRepository<SpringUsers, Integer>
SpringUsers findByUsername(String username);
List<SpringUsers> findByUserId(Integer userId);
我有一个控制器方法,它应该获取与当前经过身份验证的用户具有相同 userId(内部使用)的所有注册用户的列表:
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());
我不想将密码(即使它是加密的)传递给前端 - 所以我通过用户流式传输并将密码设置为 null,如上所示。
但是,我想知道是否有可能一开始就在查询结果中不包含用户的密码?
版本信息:
春季启动 1.4.0 & 休眠 5.0.9.Final
【问题讨论】:
【参考方案1】:您可以使用@Query
选择性地包含一些字段:
// 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);
您也可以使用Projections。首先通过引入投影接口来定义投影:
interface NoPasswordUser
Long getId();
String getUsername();
// Do not include getPassword();
然后在你的仓库中使用它:
public interface SpringUsersRepository extends CrudRepository<SpringUsers, Integer>
NoPasswordUser findByUsername(String username);
List<NoPasswordUser> findByUserId(Integer userId);
无论如何,最好不要通过 REST 或任何远程接口公开您的实体。你可以使用 DTO,这个post 可能在这个领域很有用。
【讨论】:
是的,投影似乎是一种方法 --- 如果我找不到其他解决方案,我会这样做。谢谢你的提示! 不幸的是,这似乎不适用于嵌套对象。【参考方案2】:使用@JsonIgnore,这将使它在后面可用但转换为json时不会返回
@Size(min = 8)
@JsonIgnore
private String password;
【讨论】:
【参考方案3】:我认为在从 db 获取实体时无法忽略某些字段,因为这些实体不会处于一致状态 - 它们的数据会与数据库中的数据不同。但也存在其他选项(自定义查询、投影)。
一种选择是使用constructor expressions 并在查询中直接用只需要的数据填充一些 POJO
select new my.company.SafeUser(u.username, u.email) from User u
无论如何,我认为您应该将 DTO 发送到前端,并在其中公开您在前端所需的属性。这种方法有很多优点,你可以像上面的例子那样初始化它们,或者在结果的循环中。
【讨论】:
【参考方案4】:将密码排除在写入 json 并继续读取的最佳方法是 Jackson 注释:
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String password;
类似,注册日期:
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
private Date registered = new Date();
见Jackson @JsonProperty examples
【讨论】:
如果你按munis,请写评论,解决方案有什么问题以上是关于从控制器的结果集中排除列 |弹簧数据 jpa的主要内容,如果未能解决你的问题,请参考以下文章