簡體   English   中英

如何在neo4j-ogm或spring-data-neo4j中動態更改實體類型?

[英]How to dynamically change entity types in neo4j-ogm or spring-data-neo4j?

關於“如何向Neo4j中的節點動態添加標簽”存在一個問題。 有沒有辦法動態更改實體類型?

舉個例子:

    @NodeEntity
public class User {

   @Properties(prefix = "custom")
   private Map userProperties;

}

https://neo4j.com/blog/spring-data-neo4j-5-0-release/看,我可以創建動態屬性。 運行時也可以有動態類型嗎? 我想在需要時動態地將“用戶”類型更改為“消費者” /“管理員” /“生產者”。 實體類型不是窮舉性的。

提前致謝! :)

除了來自類和接口的主要類型外,在Set<String>上還有一個@Labels注釋,該注釋被存儲/管理。

參見: https : //docs.spring.io/spring-data/neo4j/docs/current/reference/html/#reference : annotating-entities : node-entity : runtime-managed-labels

@Labels機制很棒,對於許多用例來說,這是我要說的最佳解決方案。

如果您想從存儲庫中退出另一個類,則確實需要做更多的工作。

我正在音樂相關項目中進行此操作。 我有Artist (不是抽象的,完全可以用於不知道是否是樂隊的任何事物),還有從Artist擴展來的BandSoloArtist ,帶有其他標簽:

@NodeEntity
public class Artist {}

@NodeEntity
public class Band extends Artist{}

在自定義存儲庫擴展中,我所知道的是:

interface ArtistRepository<T extends Artist> extends Repository<T, Long>, ArtistRepositoryExt {

    Optional<T> findOneByName(String name);

    // Specifying the relationships is necessary here because the generic queries won't recognize that
    // Band has a relationship to country that _should_ be loaded with default depth of 1.

    @Query("MATCH (n:Artist) WITH n MATCH p=(n)-[*0..1]-(m) RETURN p ORDER BY n.name")
    List<T> findAllOrderedByName();

    @Query("MATCH (n:Artist) WHERE id(n) = $id WITH n MATCH p=(n)-[*0..1]-(m) RETURN p")
    Optional<T> findById(@Param("id") Long id);

    <S extends T> S save(S artist);
}

interface ArtistRepositoryExt {
    Band markAsBand(Artist artist);

    SoloArtist markAsSoloArtist(Artist artist);
}

class ArtistRepositoryExtImpl implements ArtistRepositoryExt {

    private static final String CYPHER_MARK_AS_BAND = String.format(
        "MATCH (n) WHERE id(n) = $id\n" +
            "OPTIONAL MATCH (n) - [f:BORN_IN] -> (:Country)\n" +
            "REMOVE n:%s SET n:%s\n" +
            "DELETE f",
        SoloArtist.class.getSimpleName(),
        Band.class.getSimpleName());
    private static final String CYPHER_MARK_AS_SOLO_ARTIST = String.format(
        "MATCH (n) WHERE id(n) = $id\n" +
            "OPTIONAL MATCH (n) - [f:FOUNDED_IN] -> (:Country)\n" +
            "REMOVE n:%s SET n:%s\n" +
            "DELETE f",
        Band.class.getSimpleName(),
        SoloArtist.class.getSimpleName());

    private final Session session;

    public ArtistRepositoryExtImpl(Session session) {
        this.session = session;
    }

    @Override
    public Band markAsBand(Artist artist) {
        session.query(CYPHER_MARK_AS_BAND, Map.of("id", artist.getId()));
        // Needs to clear the mapping context at this point because this shared session
        // will know the node only as class Artist in this transaction otherwise.
        session.clear();
        return session.load(Band.class, artist.getId());
    }

    @Override
    public SoloArtist markAsSoloArtist(Artist artist) {
        session.query(CYPHER_MARK_AS_SOLO_ARTIST, Map.of("id", artist.getId()));
        // See above
        session.clear();
        return session.load(SoloArtist.class, artist.getId());
    }
}

盡管這很簡潔,但在更深層的嵌套類場景中,我會做出努力的想法。 另外,如果您想以多態方式使用存儲庫,請按照我的意願重新聲明派生的finder方法。

我也保留專用存儲庫。

如果這個問題仍然與您有關,請告訴我是否也對您有用。 您將在這里找到整個項目:

https://github.com/michael-simons/bootiful-music

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM