简体   繁体   English

从控制器的结果集中排除列 | 弹簧数据 jpa

[英]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:我有一个控制器方法,它应该获取与当前经过身份验证的用户具有相同 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());
}

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.我不想将密码(即使它是加密的)传递给前端 - 所以我通过用户流式传输并将密码设置为 null,如上所示。

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 Spring Boot 1.4.0 & Hibernate 5.0.9.Final

You can use @Query to selectively include some fields:您可以使用@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);

Also you can use Projections .您也可以使用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.无论如何,最好不要通过 REST 或任何远程接口公开您的实体。 You can use DTOs for that matter, this post may be useful in this area.你可以使用 DTO,这篇文章可能在这方面很有用。

Use @JsonIgnore, this will make it available in the back but will not return when transforming to json使用@JsonIgnore,这将使它在后面可用但在转换为json时不会返回

@Size(min = 8)
@JsonIgnore
private String password;

I don't think there is a way to just ignore some fields when getting the entity from db, because those entities wouldn't be in a consistent state - their data would differ from the data in the database.我认为从 db 获取实体时没有办法忽略某些字段,因为这些实体不会处于一致状态 - 它们的数据会与数据库中的数据不同。 Other options exist, though (custom query, projections).但也存在其他选项(自定义查询、投影)。

One option is to use constructor expressions and fill some POJO with only needed data in the query directly一种选择是使用构造函数表达式并在查询中直接用只需要的数据填充一些 POJO

select new my.company.SafeUser(u.username, u.email) from User u

Anyway, I think you should send DTOs to the frontend, and in it expose just the attributes you need on the frontend.无论如何,我认为您应该将 DTO 发送到前端,并在其中仅公开您在前端所需的属性。 That approach has much advantages, weather you initialize them like in the example above, or in the loop over results.这种方法有很多优点,你可以像上面的例子一样初始化它们,或者在结果循环中。

The best way to exclude password from write to json and keep to read is Jackson annotation:排除密码写入 json 并继续阅读的最佳方法是 Jackson 注释:

@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String password;

Similary, for registered date:同样,对于注册日期:

@JsonProperty(access = JsonProperty.Access.READ_ONLY)
private Date registered = new Date();

See Jackson @JsonProperty examples请参阅Jackson @JsonProperty 示例

Using @NamedNativeQuery on your entity, you can write a custom query to select everything but the password, and then map the result to a DTO @SqlResultSetMapping.在您的实体上使用@NamedNativeQuery,您可以编写一个自定义查询来选择除密码之外的所有内容,然后将结果映射到 DTO @SqlResultSetMapping。 This article provides a more detailed explanation. 本文提供了更详细的解释。

use利用

@Basic(fetch = FetchType.LAZY) @Basic(fetch = FetchType.LAZY)

for example:例如:

  //todo required annotation
    @Basic(fetch = FetchType.LAZY)
    private String password;

warning : don't forget to exclude from toString method警告:不要忘记从 toString 方法中排除

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM