Spring数据Neo4j-repository.save和@index(unique=true)
今天我尝试了SpringDataNeo4j,我终于让它以某种方式工作了 我正在使用:Spring数据Neo4j-repository.save和@index(unique=true),spring,neo4j,spring-data,unique-constraint,spring-data-neo4j,Spring,Neo4j,Spring Data,Unique Constraint,Spring Data Neo4j,今天我尝试了SpringDataNeo4j,我终于让它以某种方式工作了 我正在使用: Spring 4.0.2 弹簧数据Neo4j 3.0.0 QueryDSL 3.3.1 Neo4j 2.0.1 这是我的配置: @Configuration @EnableNeo4jRepositories(includeFilters=@Filter(value=GraphRepository.class, type=FilterType.ASSIGNABLE_TYPE)) public class Ne
- Spring 4.0.2
- 弹簧数据Neo4j 3.0.0
- QueryDSL 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;
}
}
我还尝试使用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: 从我在
AbstractGraphRespository.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
方法执行类似于获取或创建的操作:
如何修复此行为?我想要一个例外
更新#4: 好像我在找那个:
但现在我不知道如何将其与Spring数据存储库集成…如果您使用的是SDN 3.2.0+请使用failOnDuplicate属性:
@Indexed(unique = true, failOnDuplicate = true)
感谢您的反馈。你能就此提出一个jira问题吗?也许我们应该为此行为向@index添加一个属性?我已经这样做了:
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.
CREATE (n:User {email:'test@mail.com'})
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
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]
@Indexed(unique = true, failOnDuplicate = true)