首页 > 解决方案 > 如何阻止 JPA 存储库投影摘录返回多对多关系上的嵌入式列表

问题描述

我有两个实体用户和角色。它们彼此之间都有@ManyToMany关系(查找与用户关联的角色,反之亦然)。
我对每个都有几个预测,并且两个存储库都有一个excerptProjection. 每当我调用获取所有资源/api/users时,资源列表都会按预期返回。但是当我调用一个特定的资源/api/users/1时,它有一个_embedded其他类型的资源列表。

当我从 RoleRepository 中删除摘录时,调用以/api/users/1阻止嵌入式角色出现,但/api/roles/1显示嵌入式用户。

代码

实体:

public class User {
  private long id;
  private Instant createdAt;
  private Instant updatedAt;
  private String username;
  private String password;
  private String firstName;
  private String lastName;
  private String email;

  @Lazy
  @JsonIgnore
  @Where(clause = NOT_DELETED)
  @ManyToMany(cascade = CascadeType.DETACH, fetch = FetchType.LAZY)
  @JoinTable(
    name = "user_role_rel", 
    joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), 
    inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")
    )
  private Set<Role> roles = new HashSet<>();
  // other stuff omitted 
}

public class Role {
  private long id;
  private Instant createdAt;
  private Instant updatedAt;
  private String name;
  private String description;

  @Lazy
  @JsonIgnore
  @Where(clause = NOT_DELETED)
  @ManyToMany(mappedBy = "roles", cascade = CascadeType.DETACH)
  private Set<User> users = new HashSet<>();
  // other stuff omitted 
}

预测:

@Projection(name = "summary", types = { User.class })
public interface Summary {
  Long getId();
  String getUsername();
  String getFirstName();
  String getLastName();
  String getEmail();
}

@Projection(name = "summary", types = { Role.class })
public interface Summary {
  Long getId();
  String getName();
  String getDescription();
}

存储库:

@RepositoryRestResource( excerptProjection = Summary.class )
public interface UserRepository extends SoftDeleteRepository<User, Long> {}

@RepositoryRestResource
public interface RoleRepository extends SoftDeleteRepository<Role, Long> {}

请求/响应

GET /api/users/1

{
    "createdAt": "2019-06-15T10:37:16.280Z",
    "updatedAt": "2019-06-15T10:37:16.280Z",
    "username": "ironman",
    "firstName": "Tony",
    "lastName": "Stark",
    "email": "tony@starkindustries.com",
    "_id": 1,
    "_links": {
        // omitted
    }
}

GET /api/roles/1

{
    "createdAt": "2019-06-15T10:37:15.984Z",
    "updatedAt": "2019-06-15T10:37:15.984Z",
    "name": "ROLE_ADMIN",
    "description": "Admin role",
    "_id": 1,
    "_embedded": {
        "users": [
            {
                "firstName": "Tony",
                "lastName": "Stark",
                "username": "ironman",
                "email": "tony@starkindustries.com",
                "id": 1,
                "_links": {
                    // omitted
                }
            }
        ]
    },
    "_links": {
        // omitted
    }
}

第一个按预期工作,仅显示可见字段。
第二个一直在那个_embedded领域投掷。

如果我将摘录添加到两个存储库(这是我想要的),那么两个调用都会添加嵌入式列表。

对这些请求中的任何一个应用投影都会阻止嵌入列表出现,但显然默认情况下不应用投影。

有没有办法阻止这种情况发生?

标签: javaspring-data-jpa

解决方案


最近我面临着同样的问题。希望下面的代码可以帮助您解决问题。

 @Configuration
public class RepositoryConfig extends RepositoryRestConfigurerAdapter {

  @Override
  public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
    config.getProjectionConfiguration().addProjection(Summary.class);
  }
}

请查看以下网址了解更多详情:

网址


推荐阅读