为什么在某些情况下,从Spring数据Rest存储库请求JSONAPI元数据会返回递归结果?
我有一个简单的springboot/springdatarest测试应用程序,其中有一个实体“Contact”和一个crudepository。没有其他代码 当数据库为空时,在/contact上请求api+json元数据可以正常工作:为什么在某些情况下,从Spring数据Rest存储库请求JSONAPI元数据会返回递归结果?,spring,spring-mvc,spring-boot,spring-data-rest,spring-hateoas,Spring,Spring Mvc,Spring Boot,Spring Data Rest,Spring Hateoas,我有一个简单的springboot/springdatarest测试应用程序,其中有一个实体“Contact”和一个crudepository。没有其他代码 当数据库为空时,在/contact上请求api+json元数据可以正常工作: $ curl -s 'http://localhost:8080/contacts' \ -H 'Accept: application/vnd.api+json'\ -H 'Content-Type: application/hal+json'
$ curl -s 'http://localhost:8080/contacts' \
-H 'Accept: application/vnd.api+json'\
-H 'Content-Type: application/hal+json'
…产生:
{
"links" : [ {
"rel" : "self",
"href" : "http://localhost:8080/contacts"
}, {
"rel" : "profile",
"href" : "http://localhost:8080/profile/contacts"
} ],
"content" : [ {
"relTargetType" : "sdr.Contact",
"collectionValue" : true,
"rel" : null,
"value" : [ ]
} ]
}
但是,当我在数据库中放入一个联系人时,同一个请求会产生大量递归信息转储:
{
"links" : [ {
"rel" : "self",
"href" : "http://localhost:8080/contacts"
}, {
"rel" : "profile",
"href" : "http://localhost:8080/profile/contacts"
} ],
"content" : [ {
"id" : 2,
"firstName" : "Test",
"lastName" : "Contact",
"embeddeds" : {
"content" : [ ]
},
"propertyAccessor" : {
"bean" : {
"id" : 2,
"firstName" : "Test",
"lastName" : "Contact"
}
},
"persistentEntity" : {
"idProperty" : {
"name" : "id",
"rawType" : "java.lang.Long",
"field" : {
"name" : "id",
"type" : "java.lang.Long",
"modifiers" : 2,
"annotations" : [ ],
"declaredAnnotations" : [ ],
"synthetic" : false,
"declaringClass" : "sdr.Contact",
"enumConstant" : false,
"genericType" : "java.lang.Long",
"annotatedType" : {
"type" : "java.lang.Long",
"annotations" : [ ],
"declaredAnnotations" : [ ]
},
"accessible" : true
},
"association" : false,
"owner" : {
"idProperty" : {
"name" : "id",
"rawType" : "java.lang.Long",
"field" : {
"name" : "id",
"type" : "java.lang.Long",
"modifiers" : 2,
"annotations" : [ ],
"declaredAnnotations" : [ ],
"synthetic" : false,
"declaringClass" : "sdr.Contact",
"enumConstant" : false,
"genericType" : "java.lang.Long",
"annotatedType" : {
"type" : "java.lang.Long",
"annotations" : [ ],
"declaredAnnotations" : [ ]
},
"accessible" : true
},
"association" : false,
"owner" : {
"idProperty" : {
"name" : "id",
"rawType" : "java.lang.Long",
"field" : {
"name" : "id",
"type" : "java.lang.Long",
"modifiers" : 2,
"annotations" : [ ],
"declaredAnnotations" : [ ],
"synthetic" : false,
"declaringClass" : "sdr.Contact",
"enumConstant" : false,
"genericType" : "java.lang.Long",
"annotatedType" : {
"type" : "java.lang.Long",
"annotations" : [ ],
"declaredAnnotations" : [ ]
},
"accessible" : true
},
"association" : false,
"owner" : {
"idProperty" : {
"name" : "id",
"rawType" : "java.lang.Long",
"field" : {
"name" : "id",
"type" : "java.lang.Long",
"modifiers" : 2,
"annotations" : [ ],
"declaredAnnotations" : [ ],
"synthetic" : false,
"declaringClass" : "sdr.Contact",
"enumConstant" : false,
"genericType" : "java.lang.Long",
"annotatedType" : {
"type" : "java.lang.Long",
"annotations" : [ ],
"declaredAnnotations" : [ ]
},
"accessible" : true
},
"association" : false,
"owner" : {
"idProperty" : {
"name" : "id",
"rawType" : "java.lang.Long",
"field" : {
"name" : "id",
"type" : "java.lang.Long",
"modifiers" : 2,
"annotations" : [ ],
"declaredAnnotations" : [ ],
"synthetic" : false,
"declaringClass" : "sdr.Contact",
"enumConstant" : false,
"genericType" : "java.lang.Long",
"annotatedType" : {
"type" : "java.lang.Long",
"annotations" : [ ],
"declaredAnnotations" : [ ]
},
"accessible" : true
},
"association" : false,
"owner" : {
"idProperty" : {
"name" : "id",
"rawType" : "java.lang.Long",
"field" : {
"name" : "id",
"type" : "java.lang.Long",
"modifiers" : 2,
"annotations" : [ ],
"declaredAnnotations" : [ ],
"synthetic" : false,
"declaringClass" : "sdr.Contact",
"enumConstant" : false,
"genericType" : "java.lang.Long",
"annotatedType" : {
"type" : "java.lang.Long",
"annotations" : [ ],
"declaredAnnotations" : [ ]
},
"accessible" : true
},
"association" : false,
"owner" : {
"idProperty" : {
"name" : "id",
"rawType" : "java.lang.Long",
"field" : {
"name" : "id",
"type" : "java.lang.Long",
"modifiers" : 2,
"annotations" : [ ],
"declaredAnnotations" : [ ],
"synthetic" : false,
"declaringClass" : "sdr.Contact",
"enumConstant" : false,
"genericType" : "java.lang.Long",
"annotatedType" : {
"type" : "java.lang.Long",
"annotations" : [ ],
"declaredAnnotations" : [ ]
},
"accessible" : true
},
"association" : false,
"owner" : {
"idProperty" : {
"name" : "id",
"rawType" : "java.lang.Long",
"field" : {
"name" : "id",
"type" : "java.lang.Long",
"modifiers" : 2,
"annotations" : [ ],
"declaredAnnotations" : [ ],
"synthetic" : false,
"declaringClass" : "sdr.Contact",
"enumConstant" : false,
"genericType" : "java.lang.Long",
"annotatedType" : {
"type" : "java.lang.Long",
"annotations" : [ ],
"declaredAnnotations" : [ ]
},
"accessible" : true
},
"association" : false,
"owner" : {
"idProperty" : {
"name" : "id",
"rawType" : "java.lang.Long",
"field" : {
"name" : "id",
"type" : "java.lang.Long",
"modifiers" : 2,
"annotations" : [ ],
"declaredAnnotations" : [ ],
"synthetic" : false,
"declaringClass" : "sdr.Contact",
"enumConstant" : false,
"genericType" : "java.lang.Long",
"annotatedType" : {
"type" : "java.lang.Long",
"annotations" : [ ],
"declaredAnnotations" : [ ]
},
"accessible" : true
},
"association" : false,
"owner" : {
"idProperty" : {
"name" : "id",
"rawType" : "java.lang.Long",
"field" : {
"name" : "id",
"type" : "java.lang.Long",
"modifiers" : 2,
"annotations" : [ ],
"declaredAnnotations" : [ ],
"synthetic" : false,
"declaringClass" : "sdr.Contact",
"enumConstant" : false,
"genericType" : "java.lang.Long",
"annotatedType" : {
"type" : "java.lang.Long",
"annotations" : [ ],
"declaredAnnotations" : [ ]
},
"accessible" : true
},
"association" : false,
"owner" : {
"idProperty" : {
"name" : "id",
"rawType" : "java.lang.Long",
"field" : {
"name" : "id",
"type" : "java.lang.Long",
"modifiers" : 2,
"annotations" : [ ],
"declaredAnnotations" : [ ],
"synthetic" : false,
"declaringClass" : "sdr.Contact",
"enumConstant" : false,
"genericType" : "java.lang.Long",
"annotatedType" : {
"type" : "java.lang.Long",
"annotations" : [ ],
"declaredAnnotations" : [ ]
},
"accessible" : true
},
"association" : false,
"owner" : {
"idProperty" : {
"name" : "id",
"rawType" : "java.lang.Long",
"field" : {
"name" : "id",
"type" : "java.lang.Long",
"modifiers" : 2,
"annotations" : [ ],
"declaredAnnotations" : [ ],
"synthetic" : false,
"declaringClass" : "sdr.Contact",
"enumConstant" : false,
"genericType" : "java.lang.Long",
"annotatedType" : {
"type" : "java.lang.Long",
"annotations" : [ ],
"declaredAnnotations" : [ ]
},
"accessible" : true
},
"association" : false,
"owner" : {
"idProperty" : {
"name" : "id",
"rawType" : "java.lang.Long",
"field" : {
"name" : "id",
"type" : "java.lang.Long",
"modifiers" : 2,
"annotations" : [ ],
"declaredAnnotations" : [ ],
"synthetic" : false,
"declaringClass" : "sdr.Contact",
"enumConstant" : false,
"genericType" : "java.lang.Long",
"annotatedType" : {
"type" : "java.lang.Long",
"annotations" : [ ],
"declaredAnnotations" : [ ]
},
"accessible" : true
},
"association" : false,
"owner" : {
"idProperty" : {
"name" : "id",
"rawType" : "java.lang.Long",
"field" : {
"name" : "id",
"type" : "java.lang.Long",
"modifiers" : 2,
"annotations" : [ ],
"declaredAnnotations" : [ ],
"synthetic" : false,
"declaringClass" : "sdr.Contact",
"enumConstant" : false,
"genericType" : "java.lang.Long",
"annotatedType" : {
"type" : "java.lang.Long",
"annotations" : [ ],
"declaredAnnotations" : [ ]
},
"accessible" : true
},
"association" : false,
"owner" : {
"idProperty" : {
"name" : "id",
"rawType" : "java.lang.Long",
"field" : {
"name" : "id",
"type" : "java.lang.Long",
"modifiers" : 2,
"annotations" : [ ],
"declaredAnnotations" : [ ],
"synthetic" : false,
"declaringClass" : "sdr.Contact",
"enumConstant" : false,
"genericType" : "java.lang.Long",
"annotatedType" : {
"type" : "java.lang.Long",
"annotations" : [ ],
"declaredAnnotations" : [ ]
},
"accessible" : true
},
"association" : false,
"owner" : {
"idProperty" : {
"name" : "id",
"rawType" : "java.lang.Long",
"field" : {
"name" : "id",
"type" : "java.lang.Long",
"modifiers" : 2,
"annotations" : [ ],
"declaredAnnotations" : [ ],
"synthetic" : false,
"declaringClass" : "sdr.Contact",
"enumConstant" : false,
"genericType" : "java.lang.Long",
"annotatedType" : {
"type" : "java.lang.Long",
"annotations" : [ ],
"declaredAnnotations" : [ ]
},
"accessible" : true
},
"association" : false,
"owner" : {
"idProperty" : {
"name" : "id",
"rawType" : "java.lang.Long",
"field" : {
"name" : "id",
"type" : "java.lang.Long",
"modifiers" : 2,
"annotations" : [ ],
"declaredAnnotations" : [ ],
"synthetic" : false,
"declaringClass" : "sdr.Contact",
"enumConstant" : false,
"genericType" : "java.lang.Long",
"annotatedType" : {
"type" : "java.lang.Long",
"annotations" : [ ],
"declaredAnnotations" : [ ]
},
"accessible" : true
},
"association" : false,
"owner" : {
"idProperty" : {
"name" : "id",
"rawType" : "java.lang.Long",
"field" : {
"name" : "id",
***SNIP, THIS GOES ON FOREVER ***
为什么会返回此递归结果?这是预期的行为吗?
其他一切正常。测试应用程序中没有JPA关系或任何其他复杂因素。我可以使用HAL浏览器添加和删除记录等
我使用的是SpringBoot 1.3.2和SpringDataREST2.4.2
以下是应用程序中的唯一实体:
@Entity
public class Contact {
private Long id;
private String firstName;
private String lastName;
public Contact() {
}
@Id
@GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Basic
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
@Basic
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
存储库:
@Repository
@RepositoryRestResource
public interface ContactRepository extends CrudRepository<Contact, Long> {
}
@存储库
@存储资源
公共接口ContactRepository扩展了Crudepository{
}
这就是应用程序中的全部代码
更新:这似乎是SpringDataREST中的一个bug。有关测试应用程序,请参阅。也可能与和在Spring Data REST中不支持JSON API,您得到的是为
+JSON
呈现的默认表示