Spring Data Neo4j - repository.save 和 @Indexed(unique=true)
Posted
技术标签:
【中文标题】Spring Data Neo4j - repository.save 和 @Indexed(unique=true)【英文标题】:Spring Data Neo4j - repository.save and @Indexed(unique=true) 【发布时间】:2014-04-17 06:02:00 【问题描述】:今天我尝试了 Spring Data Neo4j,我终于得到了它不知何故...
我正在使用:
春季 4.0.2 Spring Data Neo4j 3.0.0 查询DSL 3.3.1 Neo4j 2.0.1这是我的配置:
@Configuration
@EnableNeo4jRepositories(includeFilters=@Filter(value=GraphRepository.class, type=FilterType.ASSIGNABLE_TYPE))
public class Neo4jConfig extends Neo4jConfiguration
public Neo4jConfig()
setBasePackage("my.base.package");
@Bean
public GraphDatabaseService graphDatabaseService()
return new GraphDatabaseFactory().newEmbeddedDatabase("/tmp/neo4j");
我的领域类:
@NodeEntity
@QueryEntity
public class User implements Persistable<Long>
@GraphId private Long id;
public Long getId() return id;
@NotNull @NotBlank @Email
@Indexed(unique=true)
private String email;
public String getEmail() return email;
void setEmail(String email) this.email = email;
@Override
public boolean isNew()
return id==null;
@Override
public int hashCode()
return id == null ? System.identityHashCode(this) : id.hashCode();
@Override
public boolean equals(Object obj)
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (id == null)
if (other.id != null)
return false;
else if (!id.equals(other.id))
return false;
return true;
还有我的存储库:
interface UserRepository extends GraphRepository<User>, CypherDslRepository<User>
我可以在数据库中成功创建一个用户,然后通过以下方式检索它:
User u = repo.query(
start(allNodes("user"))
.where(toBooleanExpression(QUser.user.email.eq("my@email.com")))
.returns(node("user")), new HashMap<String, Object>())
.singleOrNull();
但是:如果我现在再次调用我的创建代码,它不会因为@Indexed(unique=true) String email
而引发异常,它只是覆盖了数据库。
并且:如果我尝试使用不同的电子邮件值创建第二个 User
,则会覆盖旧用户。
创建代码就这么简单:
User u = new User();
u.setEmail("some@email-address.com");
repo.save(u);
我还尝试使用 Neo4j 的独立版本而不是嵌入式版本,结果完全相同。在我可以看到的 webadmin 视图中,它创建了一些索引:
Node Indexes: Relationship Indexes:
User "type":"exact" __rel_types__ "type":"exact"
lucene lucene
调试输出还告诉我 Spring 创建了一个索引:
2014-03-12 21:00:34,176 DEBUG o.s.data.neo4j.support.schema.SchemaIndexProvider: 35 - CREATE CONSTRAINT ON (n:`User`) ASSERT n.`email` IS UNIQUE
2014-03-12 21:00:34,177 DEBUG o.s.data.neo4j.support.query.CypherQueryEngine: 63 - Executing cypher query: CREATE CONSTRAINT ON (n:`User`) ASSERT n.`email` IS UNIQUE params
更多调试输出:
curl -v http://localhost:7474/db/data/index/node
"User" :
"template" : "http://localhost:7474/db/data/index/node/User/key/value",
"provider" : "lucene",
"type" : "exact"
curl -v http://localhost:7474/db/data/schema/index
[
"property_keys" : [ "email" ],
"label" : "User"
]
curl -v http://localhost:7474/db/data/schema/constraint
[
"property_keys" : [ "email" ],
"label" : "User",
"type" : "UNIQUENESS"
]
我真的无法想象我在这里做错了什么......
请帮帮我!
更新 #1:
根据我在AbstractGraphRepository.save
中看到的内容,它使用Neo4jTemplate.save
表示:
Stores the given entity in the graph, if the entity is already attached to the graph, the node is updated, otherwise a new node is created.
所以我假设它总是“认为”我的实体已经被附加。但是为什么?
更新 #2:
如果我去 webadmin 并且只做两次:
CREATE (n:User email:'test@mail.com')
我得到一个错误。所以我的 Java 代码或 SDN 一定有问题...
更新 #3:
Spring Data Neo4j 的 save
方法执行类似 GET 或 CREATE 的操作:
User u1 = new User();
u1.setEmail("a@email.com");
repo.save(u1); // creates node with id=0
User u2 = new User();
u2.setEmail("b@email.com");
repo.save(u2); // creates node with id=1
User u3 = new User();
u3.setEmail("a@email.com");
repo.save(u3); // updates and returns node with id=0
如何解决此问题?我想要一个例外。
更新 #4:
好像我在找那个:http://docs.neo4j.org/chunked/stable/rest-api-unique-indexes.html#rest-api-create-a-unique-node-or-return-fail-create
Map<String, Object> prop1 = new HashMap<String, Object>();
prop1.put("email", "abc@mail.com");
neo4jTemplate.createNodeAs(User.class, prop1);
Map<String, Object> prop2 = new HashMap<String, Object>();
prop2.put("email", "abc@mail.com");
neo4jTemplate.createNodeAs(User.class, prop2);
这样它按预期工作,至少我得到一个异常:
org.neo4j.rest.graphdb.RestResultException: Node 7 already exists with label User and property "email"=[abc@mail.com]
但现在我不知道如何将它与 Spring Data Repository 集成......
【问题讨论】:
感谢您的反馈。你能提出一个关于它的jira问题吗?也许我们应该为这种行为添加一个属性到@Indexed? 我已经做到了:jira.spring.io/browse/DATAGRAPH-445 【参考方案1】:如果您使用的是 SDN 3.2.0+,请使用 failOnDuplicate 属性:
@Indexed(unique = true, failOnDuplicate = true)
【讨论】:
以上是关于Spring Data Neo4j - repository.save 和 @Indexed(unique=true)的主要内容,如果未能解决你的问题,请参考以下文章
IgnoreCase Finder 不适用于 Spring Data Rest 和 Neo4J
Neo4j:不知道如何将图形映射到 Spring Data bean