gpt4 book ai didi

java - Spring Data Rest - 存储库继承创建奇怪的搜索端点

转载 作者:太空宇宙 更新时间:2023-11-04 10:02:21 24 4
gpt4 key购买 nike

基于 stackoverflow 上的不同线程,我尝试使用 Spring Data Rest 实现软删除行为。基本上,许多 JPA 查询需要使用 @Query 注释进行覆盖。当我在实际存储库上使用 @Query 和所有 @PreAuthorize、@PostFilter 等注释时,一切都很好,但我想在我自己的存储库类型中推广软删除,我想从中派生那些通过 Spring Data Rest 导出的存储库。

这是我所做的:1)BaseEntity,以便SoftDeleteRepository中的@Query注释知道如何识别实体类型2) SoftDeletable 具有软删除标志如何可用的契约(Contract)3)将所有@Query注释放入方法的SoftDeletionRepository4)TrainingRequestRepository扩展了SoftDeletionRepository,添加了安全注释,然后由Spring Data Rest导出。

public interface BaseEntity {
public Long getId();
public void setId(Long id);
}

public interface SoftDeletable {
public Boolean getDeleted();
public void setDeleted(Boolean deleted);
}

@RepositoryRestResource
public interface SoftDeleteRepository<T extends BaseEntity & SoftDeletable, I extends Serializable> extends CrudRepository<T, I> {

@Query("update #{#entityName} e set e.deleted = true where e.id = ?#{#request.id}")
@Modifying
@Override
public void delete(@Param("request") T entity);

@Transactional
@Query("update #{#entityName} e set e.deleted = true where e.id = ?1")
@Modifying
@Override
public void deleteById(I id);

@Query("update #{#entityName} e set e.deleted = true")
@Transactional
@Modifying
@Override
public void deleteAll();

@Query("select e from #{#entityName} e where e.deleted = false")
@Override
public Iterable<T> findAll();

@Transactional(readOnly = true)
@Query("select e from #{#entityName} e where e.id in ?1 and e.deleted = false")
@Override
public Iterable<T> findAllById(Iterable<I> requests);

@Transactional(readOnly = true)
@Query("select e from #{#entityName} e where e.id = ?1 and e.deleted = false")
@Override
public Optional<T> findById(@Param("id") I id);

@Transactional(readOnly = true)
@Query("select e from #{#entityName} e where e.deleted = true")
public Iterable<T> findDeleted();

@Override
@Transactional(readOnly = true)
@Query("select count(e) from #{#entityName} e where e.deleted = false")
public long count();

}

@RepositoryRestResource
public interface TrainingRequestRepository extends SoftDeleteRepository<TrainingRequest, Long> {

@PreAuthorize("hasAuthority('ADMIN') or principal.company.id == #request.owner.id")
@Override
public void delete(@Param("request") TrainingRequest request);

@PreAuthorize("hasAuthority('ADMIN') or requests.?[owner.id != principal.company.id].empty")
@Override
public void deleteAll(Iterable<? extends TrainingRequest> entities);

@PreAuthorize("hasAuthority('ADMIN') or @companyService.isOwnerOfRequest(id, principal)")
@Override
public void deleteById(Long id);

@PreAuthorize("hasAuthority('ADMIN')")
@Override
public void deleteAll();

@PreAuthorize("isFullyAuthenticated()")
@PostFilter("hasAuthority('ADMIN') or hasAuthority('TRAINER') or filterObject.owner.id == principal.company.id")
@Override
public Iterable<TrainingRequest> findAll();

@PreAuthorize("isFullyAuthenticated()")
@PostFilter("hasAuthority('ADMIN') or hasAuthority('TRAINER') or !filterObject.owner.?[id == #root.principal.company.id].empty")
@Override
public Iterable<TrainingRequest> findAllById(Iterable<Long> requests);

@PreAuthorize("isFullyAuthenticated()")
@PostAuthorize("hasAuthority('ADMIN') or hasAuthority('TRAINER') or @ownershipValidator.isOwnerOf(principal.company, returnObject.orElse(null))")
@Override
public Optional<TrainingRequest> findById(@Param("id") Long id);

@PreAuthorize("isFullyAuthenticated()")
@PostFilter("hasAuthority('ADMIN') or hasAuthority('TRAINER') or filterObject.owner.id == principal.company.id")
@Query("select e from #{#entityName} e where e.deleted = true")
public Iterable<TrainingRequest> findDeleted();

@PreAuthorize("hasAuthority('ADMIN') or (requests.?[id != null].empty or requests.?[owner.id != principal.owner.id].empty)")
@Override
public <S extends TrainingRequest> Iterable<S> saveAll(Iterable<S> requests);

@PreAuthorize("hasAuthority('ADMIN') or (hasAuthority('CUSTOMER') and (#request.id == null or #request.owner.id == principal.owner.id))")
@Override
public <S extends TrainingRequest> S save(@Param("request") S request);

}

一切都运转良好!我可以使用 HTTP DELETE 删除实例,并且可以验证数据库中是否仅更改了“已删除”标志。甚至安全注释也得到了遵守,因此我们可以得出结论,两个存储库(父级和子级)中的注释都变得有效。

但是:当我点击存储库的/search 端点时,我可以看到存储库中提到的所有方法的端点。我看起来 TrainingRequestRepository 中的所有方法都被列为搜索端点:

curl -s -XGET -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" http://localhost:2222/trainingRequests/search
{
"_links" : {
"findById" : {
"href" : "http://localhost:2222/trainingRequests/search/findById{?id}",
"templated" : true
},
"deleteById" : {
"href" : "http://localhost:2222/trainingRequests/search/deleteById{?id}",
"templated" : true
},
"count" : {
"href" : "http://localhost:2222/trainingRequests/search/count"
},
"delete" : {
"href" : "http://localhost:2222/trainingRequests/search/delete{?request}",
"templated" : true
},
"findAllById" : {
"href" : "http://localhost:2222/trainingRequests/search/findAllById{?requests}",
"templated" : true
},
"findAll" : {
"href" : "http://localhost:2222/trainingRequests/search/findAll"
},
"deleteAll" : {
"href" : "http://localhost:2222/trainingRequests/search/deleteAll"
},
"findOwn" : {
"href" : "http://localhost:2222/trainingRequests/search/findOwn"
},
"findByOwner" : {
"href" : "http://localhost:2222/trainingRequests/search/findByOwner{?owner}",
"templated" : true
},
"findForeign" : {
"href" : "http://localhost:2222/trainingRequests/search/findForeign"
},
"findByTraining" : {
"href" : "http://localhost:2222/trainingRequests/search/findByTraining{?training}",
"templated" : true
},
"findDeleted" : {
"href" : "http://localhost:2222/trainingRequests/search/findDeleted"
},
"self" : {
"href" : "http://localhost:2222/trainingRequests/search"
}
}
}

如果有人能给我指明方向,那就太好了!

编辑:问题是:为什么我在/trainingRequests/search 端点中看到 findAll、delete、deleteAll 等方法,而列表中应该只有 findDeleted、findByTraining、findForeign、findByOwner、findOwn 。如果没有 SoftDeletionRepository 作为 TrainingRequestRepository 的父级,那么它们就不会出现在列表中。

最佳答案

问题在于 SpringDataRest 自动为每个模型生成 CRUD 端点,并按照 HATEOS 范例公开它们。

如果不需要此功能,只需删除 SpringDataRest 依赖即可。[编辑]我刚刚重新阅读了问题标题。 @RepositoryRestResource 是引入自动生成的端点,而不是继承。[/编辑]

如果您需要此功能,您应该配置要公开的内容。有官方文档here ,以下示例取自 here

# Exposes all public repository interfaces but considers @(Repository)RestResource\u2019s `exported flag.
spring.data.rest.detection-strategy=default

# Exposes all repositories independently of type visibility and annotations.
spring.data.rest.detection-strategy=all

# Only repositories annotated with @(Repository)RestResource are exposed, unless their exported flag is set to false.
spring.data.rest.detection-strategy=annotated

# Only public repositories annotated are exposed.
spring.data.rest.detection-strategy=visibility

关于java - Spring Data Rest - 存储库继承创建奇怪的搜索端点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53335903/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com