Spring Data Neo4j多态关联出现嵌入式

时间:2015-06-29 15:54:27

标签: spring-data-neo4j spring-data-rest

我遇到了通过休息将关系暴露给子类型的问题。 我有一个名为Page:

的抽象类
@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 {

}

一个应该管理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分配给歌手领域时,它会抱怨它无法从String转换为Musician。如果我提供json而不是uri,那么它会创建一个具有相同字段值的新音乐家。 因此,当从实体引用子类型Musician时,它被视为不是由它的超类型的存储库管理。我怎样才能使歌手像链接部分下的其他相关顶级资源一样导出,并且可以通过接受uri来分配现有资源? 或者根本不可能?

1 个答案:

答案 0 :(得分:2)

我相信你需要单独的Musician,Book和Song for Spring Data Rest的存储库来正确地确定实体之间的关系。一旦修复,它应该按照您期望的方式运行 - 返回嵌入式实体的链接而不是JSON,并在发布嵌入式实体时接受uri。

您可能需要查看此答案,以了解如何在存储库定义中处理继承:

https://stackoverflow.com/a/27549198/4601679