如果对象不存在于neo4j数据库中,请插入该对象

如果对象不存在于neo4j数据库中,请插入该对象,neo4j,spring-data,spring-data-neo4j,Neo4j,Spring Data,Spring Data Neo4j,我有一个物体看起来像这样 import lombok.Data; import org.neo4j.ogm.annotation.GraphId; import org.neo4j.ogm.annotation.NodeEntity; import org.neo4j.ogm.annotation.Relationship; import java.util.HashSet; import java.util.Set; @Data @NodeEntity public class GPlay

我有一个物体看起来像这样

import lombok.Data;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;

import java.util.HashSet;
import java.util.Set;

@Data
@NodeEntity
public class GPlayer {

    @GraphId
    private Long id;
    @Relationship(type = "comrade", direction = Relationship.UNDIRECTED)
    private Set<GPlayer> comrades;
    // @Indexed(unique = true) doesn't work in v4
    private String name;

    /**
     * Adds new comrade.
     *
     * @param comrade comrade
     */
    public void acquainted(GPlayer comrade) {
        if (null == comrades) {
            comrades = new HashSet<>();
        } else {
            if (comrades.contains(comrade)) {
                return;
            }
        }
        comrades.add(comrade);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        if (!super.equals(o)) return false;

        GPlayer gPlayer = (GPlayer) o;

        if (!id.equals(gPlayer.id)) return false;
        return name.equals(gPlayer.name);
    }

    @Override
    public int hashCode() {
        int result = super.hashCode();
        result = 31 * result + id.hashCode();
        result = 31 * result + name.hashCode();
        return result;
    }

    @Override
    public String toString() {
        return "GPlayer{" +
                "id=" + id +
                ", comrades=" + comrades +
                ", name='" + name + '\'' +
                '}';
    }
}
public interface GraphPlayerRepository extends GraphRepository<GPlayer> {
    List<GPlayer> findAll();
    GPlayer findByName(String name);
}
private Long createPlayer(String playerName, String comrade, GraphPlayerRepository gRepo) {
    GPlayer gPlayer = gRepo.findByName(playerName);
    if (null == gPlayer) {
        gPlayer = new GPlayer();
        gPlayer.setName(playerName);
        if (null != comrade) {
            gPlayer.acquainted(gRepo.findByName(comrade));
        }
        gRepo.save(gPlayer);
        LOGGER.info("Created new GRAPH player: {}", gPlayer);
    } else {
        gPlayer.acquainted(gRepo.findByName(comrade));
        gRepo.save(gPlayer);
        LOGGER.info("Updated player: {}", gPlayer);
    }
    return gPlayer.getId();
}
要插入,我喜欢这样

import lombok.Data;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;

import java.util.HashSet;
import java.util.Set;

@Data
@NodeEntity
public class GPlayer {

    @GraphId
    private Long id;
    @Relationship(type = "comrade", direction = Relationship.UNDIRECTED)
    private Set<GPlayer> comrades;
    // @Indexed(unique = true) doesn't work in v4
    private String name;

    /**
     * Adds new comrade.
     *
     * @param comrade comrade
     */
    public void acquainted(GPlayer comrade) {
        if (null == comrades) {
            comrades = new HashSet<>();
        } else {
            if (comrades.contains(comrade)) {
                return;
            }
        }
        comrades.add(comrade);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        if (!super.equals(o)) return false;

        GPlayer gPlayer = (GPlayer) o;

        if (!id.equals(gPlayer.id)) return false;
        return name.equals(gPlayer.name);
    }

    @Override
    public int hashCode() {
        int result = super.hashCode();
        result = 31 * result + id.hashCode();
        result = 31 * result + name.hashCode();
        return result;
    }

    @Override
    public String toString() {
        return "GPlayer{" +
                "id=" + id +
                ", comrades=" + comrades +
                ", name='" + name + '\'' +
                '}';
    }
}
public interface GraphPlayerRepository extends GraphRepository<GPlayer> {
    List<GPlayer> findAll();
    GPlayer findByName(String name);
}
private Long createPlayer(String playerName, String comrade, GraphPlayerRepository gRepo) {
    GPlayer gPlayer = gRepo.findByName(playerName);
    if (null == gPlayer) {
        gPlayer = new GPlayer();
        gPlayer.setName(playerName);
        if (null != comrade) {
            gPlayer.acquainted(gRepo.findByName(comrade));
        }
        gRepo.save(gPlayer);
        LOGGER.info("Created new GRAPH player: {}", gPlayer);
    } else {
        gPlayer.acquainted(gRepo.findByName(comrade));
        gRepo.save(gPlayer);
        LOGGER.info("Updated player: {}", gPlayer);
    }
    return gPlayer.getId();
}

但它看起来相当冗长。有没有办法让它更简单?

您可以使用名称作为实体的id

@Index(unique=true, primary=true)
private String name;
然后无需声明
findByName
方法,只需使用
Neo4jRepository

public interface GraphPlayerRepository extends Neo4jRepository<GPlayer, String> {
...
}
public interface GraphPlayerRepository扩展了Neo4jRepository{
...
}
并使用
repository.findOne(name)
从名称中获取玩家

也就是说,hashCode和Equals的实现是不正确的:强烈建议不要在这些代码中使用
长id
。看

否则,与SDN无关,但改进可能包括:

  • 使用lombok生成hashcode和equals
  • 在字段级别初始化哈希集

您还可以迁移到SDN 5并使用可选的返回类型来避免if/else空性检查块。

是否将
@Index
用作
GraphId
的替代品?不太可能,您仍然需要带有SDN 4的@GraphId。但是主索引将用作实体的查找键。因此我必须将
Long id
保留为@graphId?是(对于SDN 4。对于SDN 5,不再需要它)。