如果 neo4j db 中不存在则插入对象
insert object if it not exist in neo4j db
我有一个看起来像这样的对象
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 + '\'' +
'}';
}
}
我想将其存储在 Neo4j
中,具有唯一性 name
。因此,当我插入 GPlayer
- 如果具有此类名称的对象不存在,我不想插入它。
我有这样的存储库
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> {
...
}
并使用repository.findOne(name)
从名称中获取玩家。
也就是说,hashCode 和 Equals 的实现是不正确的:强烈建议不要在这些中使用 Long id
。参见 here。
否则,与 SDN 无关,但改进可能包括:
- 使用lombok生成hashcode和equals
- 在字段级别初始化 hashSet
您还可以迁移到 SDN 5 并使用可选 return 类型来避免 if/else 无效检查块。
我有一个看起来像这样的对象
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 + '\'' +
'}';
}
}
我想将其存储在 Neo4j
中,具有唯一性 name
。因此,当我插入 GPlayer
- 如果具有此类名称的对象不存在,我不想插入它。
我有这样的存储库
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> {
...
}
并使用repository.findOne(name)
从名称中获取玩家。
也就是说,hashCode 和 Equals 的实现是不正确的:强烈建议不要在这些中使用 Long id
。参见 here。
否则,与 SDN 无关,但改进可能包括:
- 使用lombok生成hashcode和equals
- 在字段级别初始化 hashSet
您还可以迁移到 SDN 5 并使用可选 return 类型来避免 if/else 无效检查块。