Jackson 模块在 Spring Data REST 中处理抽象聚合根及其子类

Jackson module to handle abstract aggregate root and its subclasses in Spring Data REST

我有 Spring 基于数据 REST 的应用程序和存储库

public interface CriterionRepository extends JpaRepository<Criterion, Long> {
}

Criterion 是基础 class:

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Criterion extends AbstractEntity {}

NameCriterion是它的子class

@Entity
public class NameCriterion extends Criterion {
    private final String name;
}

Spring Data REST 将存储库导出为 REST 资源,可以在 http://localhost:8080/api/criteria/

访问它

导出的资源如下所示:

{
    "_embedded": {
        "nameCriteria": [{
                "_links": {
                    "self": {
                        "href": "http://localhost:8080/api/nameCriterion/1"
                    },
                    "nameCriterion": {
                        "href": "http://localhost:8080/api/nameCriterion/1"
                    }
                }
            }
        ]
    },
    "_links": {
        "self": {
            "href": "http://localhost:8080/api/criteria"
        },
        "profile": {
            "href": "http://localhost:8080/api/profile/criteria"
        }
    },
    "page": {
        "size": 20,
        "totalElements": 1,
        "totalPages": 1,
        "number": 0
    }
}

当我尝试跟随自己 link 时,http://localhost:8080/api/nameCriterion/1

没有映射

虽然我可以关注 http://localhost:8080/api/criteria/1,但我得到的回复没有来自 NameCriterion

name 字段
{
    "_links": {
        "self": {
            "href": "http://localhost:8080/api/nameCriterion/1"
        },
        "nameCriterion": {
            "href": "http://localhost:8080/api/nameCriterion/1"
        }
    }
}

我的假设是 REST 导出器中定义的 Jackson 映射器存在问题,未正确调整以处理 JpaRepository 中用作聚合根的抽象 class Criterion

我应该应用什么 Jackson 定制才能使其正常工作?

换句话说,我应该创建什么 Jackson 模块?

无需创建 Jackson 模块。要对继承的实体使用单个 table,我们可以使用 @RestResource 注释将它们标记为相同的资源:

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Table(name = "criteria")
public abstract class Criterion extends AbstractEntity {
}

@RestResource(rel = "criteria", path = "criteria")
@Entity
public class NameCriterion extends Criterion {

    private String name;
}

@RestResource(rel = "criteria", path = "criteria")
@Entity
public class TitleCriterion extends Criterion {

    private String title;
}

@RepositoryRestResource(path = "criteria", collectionResourceRel = "criteria", itemResourceRel = "criterion")
public interface CriterionRepository extends JpaRepository<Criterion, Long> {
}

因此可以在一次输出中获取所有资源(NameCriterion 和 TitleCriterion):

GET http://localhost:8080/api/criteria

{
  "_embedded": {
    "criteria": [
      {
        "name": "name1",
        "_links": {
          "self": {
            "href": "http://localhost:8080/api/criteria/1"
          },
          "nameCriterion": {
            "href": "http://localhost:8080/api/criteria/1"
          }
        }
      },
      {
        "title": "title1",
        "_links": {
          "self": {
            "href": "http://localhost:8080/api/criteria/2"
          },
          "titleCriterion": {
            "href": "http://localhost:8080/api/criteria/2"
          }
        }
      }
    ]
  }
}

GET http://localhost:8080/api/criteria/1
{
  "name": "name1",
  "_links": {
    "self": {
      "href": "http://localhost:8080/api/criteria/1"
    },
    "nameCriterion": {
      "href": "http://localhost:8080/api/criteria/1"
    }
  }
}

GET http://localhost:8080/api/criteria/2
{
  "title": "title1",
  "_links": {
    "self": {
      "href": "http://localhost:8080/api/criteria/2"
    },
    "titleCriterion": {
      "href": "http://localhost:8080/api/criteria/2"
    }
  }
}

工作example