【问题标题】:spring-data-rest return multiple projections at once (compose projections)spring-data-rest 一次返回多个投影(组合投影)
【发布时间】:2020-02-13 09:07:08
【问题描述】:

是否有可能组合多个投影?这是我用例的最佳方法吗?

例如,我有 CarInBazar 类的这些预测:

  • SimpleCarInList
  • WidgetForHotSale
  • NumberOfItemViews
  • FullCarData
  • CarMainImage
  • CarMainImageIconSize
  • 汽车附加图像

前端现在正在制作一些 UI 页面,这需要其中一些投影。

我应该这样做:

  1. 前端将对具有不同投影的同一资源进行多次请求
  2. 为前端的每个屏幕实现投影(复制 NumberOfItemViews 计算等内容,...)
  3. 使用继承并利用extends 关键字进行特定预测。即:
    @Projection(name = "screen-dashboardHome", types = {CarInBazar.class})
    public interface DashboardHomeProjectionForCarInBazar extends SimpleCarInList,
        WidgetForHotSale, CarMainImageIconSize {
    }
  1. 是否有可能一次请求更多的投影?它可能比使用提供的配置文件在 UI 中呈现。

编辑:根据要求,提供投影定义示例:

import org.springframework.data.rest.core.config.Projection;

import java.awt.*;
import java.util.Date;

@Projection(name = "CarMainImage", types = {CarInBazar.class})
public interface CarMainImage {
    Date getLastUpdateDate();

    Image getMainImage();

    default String getMainImageAdditionalInformation() {
        final var updated = this.getLastUpdateDate().getTime();
        final var created = this.getCreatedAtDate().getTime();

        if (created >= (updated - 10 minutes)) {
            return "some business logic on not published fields";
        } else {
            return "could happen not only in spel";
        }
    }
}

许多投影不包含任何业务逻辑,只是过滤字段。

【问题讨论】:

  • 不了解投影的定义方式和实际实体,没有简单的方法可以帮助您。
  • 嗨@Aivaras,我已经用项目的示例投影编辑了问题。 PS:除了docs.spring.io/spring-data/rest/docs/current/reference/html/…,还有其他方法可以提供投影吗?
  • 我通常会在存储库中写一个@Query,如果它涉及一个或两个具有附加接口映射回结果集的实体。在您的情况下,我们会看到投影名称列表,但不清楚是否所有这些都属于同一实体。
  • 是的,正如我在第二行回答中所说,所有这些(预测)都是针对单个模型(资源)的。
  • 我已经在单独的问题中澄清了我的主要反对意见,正如@Aivaras 所建议的那样。见stackoverflow.com/questions/60622337/…

标签: spring-data-rest hateoas


【解决方案1】:

似乎不支持(或广泛支持或容易)使用多个投影。使用来自@Aivaras 评论的建议,我使用了这种方法:

带有自定义 JPQL 查询的存储库代码:

@Repository
@RepositoryRestResource
@Transactional(readOnly = true)
public interface SomeRepository extends PagingAndSortingRepository<Some, Long> {
    Page<Some> findByNameContaining(String namePart, Pageable pageable);

    @Query("select new sk.qpp.documents.projections.SomeCustomViewByQuery(s.name, s.startDate, s.endDate, s.goLiveDate, 42) from Some s where s.id = :id")
    Optional<SomeCustomViewByQuery> getByIdProjectedForSpecialScreen(Long id);
}

SomeCustomViewByQuery 类只是简单的 DTO 之类的东西。使用 lombok 它看起来像:

@Value
public class SomeCustomViewByQuery {
    private String name;

    private Date startDate;

    private Date endDate;

    private Date goLiveDate;

    // TODO make SomeHealth to be enum and specific logic behind it.
    String getSomeHealth() {
        final var start = this.getStartDate().getTime();
        final var end = this.getEndDate().getTime();
        final var goLive = this.getGoLiveDate().getTime();
        final var now = System.currentTimeMillis();

        if (now < start) {
            return "not started yet";
        } else {
            if (now < end) {
                return "work in progress";
            } else {
                if (now < goLive) {
                    return "passed end, but before goLive";
                } else {
                    return "something after goLive time";
                }
            }
        }
    }

    private int unicornsCount;
}

这样,我可以进行手工查询 (JQPL) 并创建自定义 DTO 实例。它很方便,我需要通过聚合(count、avg、max、min、...)和其他东西对其他表进行一些连接,这在数据库方面做得更好。

【讨论】:

    猜你喜欢
    • 2017-07-27
    • 2018-04-18
    • 2016-01-20
    • 1970-01-01
    • 2018-03-05
    • 1970-01-01
    • 2015-05-01
    • 2019-01-27
    • 1970-01-01
    相关资源
    最近更新 更多