Spring 数据 Neo4j 多态关联出现嵌入
Spring Data Neo4j polymorphic association appears embedded
我在通过 rest 公开与子类型的关系时遇到问题。
我有一个名为 Page:
的摘要 class
@NodeEntity
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "category", visible = true)
@JsonSubTypes({ @Type(value = Musician.class), @Type(value = Book.class),
@Type(value = Song.class) })
public abstract class Page extends BaseEntity{
@Fetch
@CreatedBy
private User creator;
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@GraphProperty(propertyType = Long.class)
@CreatedDate private LocalDateTime timeCreated;
@NotEmpty
@Size(min = 1, max = 160)
@Indexed(indexType = IndexType.FULLTEXT, indexName = "search")
private String screenname;
@Fetch
@RelatedTo(type = "CHANNEL")
private Channel channel = new Channel();
public Channel getChannel() {
return channel;
}
public void setChannel(Channel channel) {
this.channel = channel;
}
public String getScreenname() {
return screenname;
}
public void setScreenname(String screenname) {
this.screenname = screenname;
}
// This is to work around the bug where type name is not exported by SDR.
@JsonGetter(value = "category")
public String getType() {
return this.getClass().getSimpleName();
}
public User getCreator() {
return creator;
}
public void setCreator(User creator) {
this.creator = creator;
}
public LocalDateTime getTimeCreated() {
return timeCreated;
}
public void setTimeCreated(LocalDateTime timeCreated) {
this.timeCreated = timeCreated;
}
}
歌曲和音乐家两个子类型:
@NodeEntity
@JsonTypeName("Song")
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="category", visible=true)
public class Song extends Page {
@Fetch
@RelatedTo(type = "SINGER")
private Musician singer;
public Musician getSinger() {
return singer;
}
public void setSinger(Musician singer) {
this.singer = singer;
}
}
和
@NodeEntity
@JsonTypeName("Musician")
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="category", visible=true)
public final class Musician extends Page {
}
还有一个应该管理页面所有子类型的存储库:
@RepositoryRestResource(collectionResourceRel = "pages", path = "pages")
public interface PageRepository extends PagingAndSortingRepository<Page, Long> {
org.springframework.data.domain.Page<Musician> findMusicianByScreennameLike(@Param("0") String screenname, Pageable page);
}
当我从我的 api 中获取 Song 实例时,json 看起来像:
{
"uuid" : "ee9daf8b-4285-45bb-a583-e37f54284c43",
"timeCreated" : null,
"screenname" : "songtest",
"singer" : null,
"id" : 213,
"category" : "Song",
"_links" : {
"self" : {
"href" : "http://localhost:8080/api/pages/213"
},
"channel" : {
"href" : "http://localhost:8080/api/pages/213/channel"
},
"creator" : {
"href" : "http://localhost:8080/api/pages/213/creator"
}
}
}
问题是歌手字段出现嵌入。而且我无法将现有的音乐家与这个歌手领域联系起来。当我尝试将现有音乐家的 uri 分配给歌手字段时,它抱怨说它无法从字符串转换为音乐家。如果我提供 json 而不是 uri,那么它会创建一个具有相同字段值的新音乐家。
因此,当从实体引用子类型 Musician 时,它被视为不受其超类型存储库管理。我怎样才能使歌手像链接部分下的其他相关顶级资源一样导出,并且可以通过接受 uri 分配现有资源?
或者根本不可能?
我相信您需要为 Spring Data Rest 的 Musician、Book 和 Song 单独存储库,以正确确定实体之间的关系。修复后,它应该按照您期望的方式运行 - 返回嵌入实体的链接而不是 JSON,并在发布嵌入实体时接受 uri。
您可能想看看这个答案,了解如何处理存储库定义中的继承:
我在通过 rest 公开与子类型的关系时遇到问题。 我有一个名为 Page:
的摘要 class@NodeEntity
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "category", visible = true)
@JsonSubTypes({ @Type(value = Musician.class), @Type(value = Book.class),
@Type(value = Song.class) })
public abstract class Page extends BaseEntity{
@Fetch
@CreatedBy
private User creator;
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@GraphProperty(propertyType = Long.class)
@CreatedDate private LocalDateTime timeCreated;
@NotEmpty
@Size(min = 1, max = 160)
@Indexed(indexType = IndexType.FULLTEXT, indexName = "search")
private String screenname;
@Fetch
@RelatedTo(type = "CHANNEL")
private Channel channel = new Channel();
public Channel getChannel() {
return channel;
}
public void setChannel(Channel channel) {
this.channel = channel;
}
public String getScreenname() {
return screenname;
}
public void setScreenname(String screenname) {
this.screenname = screenname;
}
// This is to work around the bug where type name is not exported by SDR.
@JsonGetter(value = "category")
public String getType() {
return this.getClass().getSimpleName();
}
public User getCreator() {
return creator;
}
public void setCreator(User creator) {
this.creator = creator;
}
public LocalDateTime getTimeCreated() {
return timeCreated;
}
public void setTimeCreated(LocalDateTime timeCreated) {
this.timeCreated = timeCreated;
}
}
歌曲和音乐家两个子类型:
@NodeEntity
@JsonTypeName("Song")
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="category", visible=true)
public class Song extends Page {
@Fetch
@RelatedTo(type = "SINGER")
private Musician singer;
public Musician getSinger() {
return singer;
}
public void setSinger(Musician singer) {
this.singer = singer;
}
}
和
@NodeEntity
@JsonTypeName("Musician")
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="category", visible=true)
public final class Musician extends Page {
}
还有一个应该管理页面所有子类型的存储库:
@RepositoryRestResource(collectionResourceRel = "pages", path = "pages")
public interface PageRepository extends PagingAndSortingRepository<Page, Long> {
org.springframework.data.domain.Page<Musician> findMusicianByScreennameLike(@Param("0") String screenname, Pageable page);
}
当我从我的 api 中获取 Song 实例时,json 看起来像:
{
"uuid" : "ee9daf8b-4285-45bb-a583-e37f54284c43",
"timeCreated" : null,
"screenname" : "songtest",
"singer" : null,
"id" : 213,
"category" : "Song",
"_links" : {
"self" : {
"href" : "http://localhost:8080/api/pages/213"
},
"channel" : {
"href" : "http://localhost:8080/api/pages/213/channel"
},
"creator" : {
"href" : "http://localhost:8080/api/pages/213/creator"
}
}
}
问题是歌手字段出现嵌入。而且我无法将现有的音乐家与这个歌手领域联系起来。当我尝试将现有音乐家的 uri 分配给歌手字段时,它抱怨说它无法从字符串转换为音乐家。如果我提供 json 而不是 uri,那么它会创建一个具有相同字段值的新音乐家。 因此,当从实体引用子类型 Musician 时,它被视为不受其超类型存储库管理。我怎样才能使歌手像链接部分下的其他相关顶级资源一样导出,并且可以通过接受 uri 分配现有资源? 或者根本不可能?
我相信您需要为 Spring Data Rest 的 Musician、Book 和 Song 单独存储库,以正确确定实体之间的关系。修复后,它应该按照您期望的方式运行 - 返回嵌入实体的链接而不是 JSON,并在发布嵌入实体时接受 uri。
您可能想看看这个答案,了解如何处理存储库定义中的继承: