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。
我有 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
{
"_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。