Spring Data Neo4j - repository.save 和 @Indexed(unique=true) [英] Spring Data Neo4j - repository.save and @Indexed(unique=true)

查看:57
本文介绍了Spring Data Neo4j - repository.save 和 @Indexed(unique=true)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天我尝试了 Spring Data Neo4j,我终于让它工作了不知何故...

Today I tried Spring Data Neo4j, I finally got it working somehow...

我正在使用:

  • Spring 4.0.2
  • Spring Data 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;
    }

}

还有我的存储库:

interface UserRepository extends GraphRepository<User>, CypherDslRepository<User> {}

<小时>

我可以在数据库中成功创建一个用户,然后通过以下方式检索它:


I can successfully create a User in DB and afterwards retrieve it via:

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) Stringemail,它只是覆盖数据库中的对象.

BUT: if I now call my create code a second time, it won't throw an exception because of @Indexed(unique=true) String email, it just overrides the the object in the DB.

AND:如果我尝试使用不同的电子邮件值创建第二个 User,旧用户将被覆盖.

AND: if I try to create a second User with a different email value, the old user get's overridden.

创建代码很简单:

User u = new User();
u.setEmail("some@email-address.com");
repo.save(u);

我还尝试使用独立版本的 Neo4j 而不是嵌入式版本,结果完全相同.在 webadmin 视图中,我可以看到,它创建了一些索引:

I also tried to use a standalone version of Neo4j instead of the embedded one, with exactly the same result. In the webadmin view I can see, that it created some Indexes:

Node Indexes:                 Relationship Indexes:

User     {"type":"exact"}     __rel_types__   {"type":"exact"}
lucene                        lucene

调试输出还告诉我 Spring 创建了一个索引:

The debug output also tells me that Spring creates an index:

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"
} ]

我真的无法想象我在这里做错了什么......

I really can't imagine what I am doing wrong here...

请帮帮我!

更新 #1:

从我在 AbstractGraphRepository.save 中看到它使用 Neo4jTemplate.save 说:

From what I've seen in AbstractGraphRepository.save it uses Neo4jTemplate.save which says:

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.

所以我假设它总是认为"我的实体已经附加了.但是为什么?

So I assume that it always "thinks" that my entity is already attached. But why?

更新 #2:

如果我去网络管理员那里做两次:

If I go to the webadmin and do simply twice:

CREATE (n:User {email:'test@mail.com'})

我收到一个错误.所以一定是我的Java代码或者SDN有问题...

I get an error. So there must be something wrong with my Java code or SDN...

更新 #3:

Spring Data Neo4j 的 save 方法执行类似 GET 或 CREATE 的操作:

Spring Data Neo4j's save Method does something like GET or 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

我该如何解决这个问题?我想要一个例外.

How can I fix this behavior? I want an exception.

更新 #4:

好像我在找那个:http://docs.neo4j.org/chunked/stable/rest-api-unique-indexes.html#rest-api-create-a-unique-节点或返回失败创建

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);

这样就按预期工作了,至少我得到了一个例外:

This way it works as expected, at least I get an exception:

org.neo4j.rest.graphdb.RestResultException: Node 7 already exists with label User and property "email"=[abc@mail.com]

但现在我不知道如何将其与 Spring Data Repository 集成...

But now I can't figure out how to integrate this with the Spring Data Repository...

推荐答案

如果您使用的是 SDN 3.2.0+,请使用 failOnDuplicate 属性:

If you are using SDN 3.2.0+ use the failOnDuplicate attribute:

@Indexed(unique = true, failOnDuplicate = true)

这篇关于Spring Data Neo4j - repository.save 和 @Indexed(unique=true)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆