【问题标题】:Spring Data Neo4J - NotInTransactionException while modifying set of nodeEntitySpring Data Neo4J - 修改 nodeEntity 集时出现 NotInTransactionException
【发布时间】:2013-09-23 04:15:46
【问题描述】:

我们正在使用带有存储库方法和注释查询的 spring-data-neo4j。以前,我们使用 SDN 与独立服务器建立休息连接。不过性能很差,所以我们决定使用带有嵌入式 neo4j 实例的 SDN。但这并没有按预期工作。

这里有一些类

节点实体

import java.util.Set;

import org.codehaus.jackson.annotate.JsonIgnore;
import org.neo4j.graphdb.Direction;
import org.springframework.data.neo4j.annotation.Fetch;
import org.springframework.data.neo4j.annotation.GraphId;
import org.springframework.data.neo4j.annotation.Indexed;
import org.springframework.data.neo4j.annotation.NodeEntity;
import org.springframework.data.neo4j.annotation.RelatedToVia;

import com.xxx.xyz.relationships.UserToAnnotation;
import com.xxx.xyz.relationships.UserToBookmark;
import com.xxx.xyz.relationships.UserToGroup;
import com.xxx.xyz.relationships.UserToLastReadMedia;
import com.xxx.xyz.relationships.UserToLicenseOwner;
import com.xxx.xyz.relationships.UserToLicenseReader;
import com.xxx.xyz.relationships.UserToUser;

/** Simple user class. */
@NodeEntity
public class Neo4jUser {

    @GraphId
    Long id;

    private String type;

    @Indexed(unique=true)
    private String emailAddress;

    @Indexed
    private String nickname;

    private String passwordHash;

    private String givenName;

    private String familyName;

    private Long birthdate;


    @JsonIgnore
    @RelatedToVia(type = "isIn", direction = Direction.OUTGOING)
    private Set<UserToGroup> memberships;

    public Neo4jUser() {
    }

    //constructor

    //getter / setter


    public void isIn(final Neo4jGroup group, final String role) {
        memberships.add(new UserToGroup(this, group, role));
    }



}

一个关系实体

package com.xxx.xyz.relationships;

import org.springframework.data.neo4j.annotation.EndNode;
import org.springframework.data.neo4j.annotation.Fetch;
import org.springframework.data.neo4j.annotation.GraphId;
import org.springframework.data.neo4j.annotation.RelationshipEntity;
import org.springframework.data.neo4j.annotation.StartNode;

import com.xxx.xyz.model.db.Neo4jGroup;
import com.xxx.xyz.model.db.Neo4jUser;

@RelationshipEntity(type="isIn")
public class UserToGroup {

    @GraphId
    Long id;

    @Fetch @StartNode
    private Neo4jUser user;

    @Fetch @EndNode
    private Neo4jGroup group;

    private String role;

    public UserToGroup(){
    }

    public UserToGroup(final Neo4jUser user, final Neo4jGroup group, final String role)
    {
        this.user = user;
        this.group = group;
        this.role = role;
    }

}

用户存储库

@Transactional
public interface UserRepository extends GraphRepository<Neo4jUser> {

//annotated cypher queries

}

spring applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/data/neo4j 
        http://www.springframework.org/schema/data/neo4j/spring-neo4j-2.0.xsd 
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

    <context:annotation-config />
    <context:spring-configured />
    <context:component-scan base-package="com.xxx.xyz.service" />

    <neo4j:config storeDirectory="data/graph.db" />

    <neo4j:repositories base-package="com.xxx.xyz.repository" />


</beans>

maven 依赖

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-neo4j</artifactId>
    <version>2.2.2.RELEASE</version>
</dependency>

当尝试使用Neo4JUser.isIn()方法修改集合memberships时,抛出以下异常

org.neo4j.graphdb.NotInTransactionException
    at org.neo4j.kernel.impl.persistence.PersistenceManager.getResource(PersistenceManager.java:252)
    at org.neo4j.kernel.impl.persistence.PersistenceManager.relationshipCreate(PersistenceManager.java:161)
    at org.neo4j.kernel.impl.core.NodeManager.createRelationship(NodeManager.java:252)
    at org.neo4j.kernel.impl.core.NodeImpl.createRelationshipTo(NodeImpl.java:578)
    at org.neo4j.kernel.impl.core.NodeProxy.createRelationshipTo(NodeProxy.java:207)
    at org.springframework.data.neo4j.support.DelegatingGraphDatabase.createRelationship(DelegatingGraphDatabase.java:125)
    at org.springframework.data.neo4j.support.mapping.EntityStateHandler.getOrCreateRelationship(EntityStateHandler.java:168)
    at org.springframework.data.neo4j.support.mapping.EntityStateHandler.useOrCreateState(EntityStateHandler.java:139)
    at org.springframework.data.neo4j.support.mapping.Neo4jEntityConverterImpl.write(Neo4jEntityConverterImpl.java:146)
    at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister$CachedConverter.write(Neo4jEntityPersister.java:179)
    at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.persist(Neo4jEntityPersister.java:249)
    at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.persist(Neo4jEntityPersister.java:231)
    at org.springframework.data.neo4j.support.Neo4jTemplate.save(Neo4jTemplate.java:293)
    at org.springframework.data.neo4j.fieldaccess.RelatedToViaCollectionFieldAccessorFactory$RelatedToViaCollectionFieldAccessor.persistEntities(RelatedToViaCollectionFieldAccessorFactory.java:99)
    at org.springframework.data.neo4j.fieldaccess.RelatedToViaCollectionFieldAccessorFactory$RelatedToViaCollectionFieldAccessor.setValue(RelatedToViaCollectionFieldAccessorFactory.java:93)
    at org.springframework.data.neo4j.fieldaccess.ManagedFieldAccessorSet.updateValue(ManagedFieldAccessorSet.java:94)
    at org.springframework.data.neo4j.fieldaccess.ManagedFieldAccessorSet.update(ManagedFieldAccessorSet.java:82)
    at org.springframework.data.neo4j.fieldaccess.ManagedFieldAccessorSet.add(ManagedFieldAccessorSet.java:108)
    at com.xxx.xyz.model.db.Neo4jUser.isIn(Neo4jUser.java:187)

我做了一些研究发现,SDN的其余连接不使用事务,嵌入式版本使用,所以NotInTransactionException是可能的。

此外,我们没想到save() 在处理具有关系的集合时会被触发。之后我们总是手动调用 save() 。这是为什么呢?

但是这里做错了什么?

感谢任何帮助!

谢谢!

【问题讨论】:

    标签: spring neo4j spring-data spring-data-neo4j


    【解决方案1】:

    这确实有点令人困惑,我也遇到过同样的问题。如果您在模型中使用关系集,则该集将由 SDN 支持。因此,如果您对集合进行任何修改,SDN 将尝试相应地更改您的数据库(即创建/删除关系)。 如果你不希望你的模型得到数据库的支持,你应该使用 Iterable。

    http://static.springsource.org/spring-data/neo4j/docs/current/reference/htmlsingle/#reference:programming_model:relationships:relatedto

    【讨论】:

    • 感谢您提供的信息。如何避免异常,需要更改/配置什么?你是怎么解决这个问题的?
    • 正如我所提到的,最简单的方法是在模型类中使用 Iterable。然后你不能无意中创建/删除关系。但是,如果您希望能够直接与模型类创建/删除关系,则需要确保它发生在事务中(使用 @Transactional)。
    • 对于@Tranactional,您还应该将其添加到您的spring配置中:
    • 假设我们坚持使用 Sets,我应该在哪里放置 @Transactional 注释以使方法 isIn() 异常安全?
    • 这取决于您希望交易持续多长时间 :) 至少,您在操作集合的方法上需要它。另请注意,默认情况下 @Transactional 仅适用于公共方法,并且仅在从外部类调用它们时(参见 docs.spring.io/spring/docs/3.2.x/spring-framework-reference/… 第 12.5.6 节)
    猜你喜欢
    • 1970-01-01
    • 2015-06-24
    • 2013-06-08
    • 2018-08-30
    • 1970-01-01
    • 1970-01-01
    • 2015-07-19
    • 2019-02-17
    • 1970-01-01
    相关资源
    最近更新 更多