spring-data-neo4j 基本的一对多关系不持久
spring-data-neo4j basic one-to-many relationship not persisting
EDIT: Sample project available on github.
我在后端项目中使用 Neo4J(Rest 图形数据库,托管在 grapheneDb 中)和 Spring 数据。
<bean id="graphDatabaseService" class="org.springframework.data.neo4j.rest.SpringCypherRestGraphDatabase">
我在两个实体之间有一个简单的一对多关系:User
和 Stay
。
编辑:我认为这与问题无关,但在 SDN4 中看到 similar problem 后,我认为我需要更新问题(那里是一个基本的 @NodeEntity
class,两个实体都在扩展这个基础 class)。
@NodeEntity
public abstract class BasicNodeEntity implements Serializable {
@GraphId
private Long nodeId;
}
public class User extends BasicNodeEntity {
@RelatedTo(type = "HAS_STAY", direction = Direction.OUTGOING)
Set<Stay> stays;
public void addStay(Stay stay) {
stays.add(stay);
}
}
public class Stay extends BasicNodeEntity {
@RelatedTo(type = "HAS_STAY", direction = Direction.INCOMING)
User user;
}
我无法坚持住超过一次。我添加给用户的第一个停留是正确的,但只是第一个。添加的下一个停留永远不会持续存在,我总是检索第一个。
我创建新住宿的方法是:
@Autowired
Neo4jOperations template;
@Transactional
private void createStay(Stay stay, User user) throws Exception {
stay = template.save(stay);
user.addStay(stay);
template.save(user);
// If i evaluate user at this point, it contains both stays
// But if I retrieve the user from the repository, it just contains
// the first stay, the second one has not persisted.
}
EDIT: 通过UserRepository
.
正确检索用户修改
public interface UserRepositoryCustom {}
public interface UserRepository extends GraphRepository<User>, UserRepositoryCustom {
User findById(String id);
}
User user = userRepository.findById(userId);
注意:我也尝试通过存储库界面而不是 Neo4jTemplate 界面保存,但我遇到了同样的问题。
两个实体都正确保存在 neo4j 数据库中,这只是一个持久性问题。
我认为这应该很容易,所以我可能遗漏了一些东西..
如有任何帮助,我们将不胜感激。
相关版本:
<spring.version>4.0.5.RELEASE</spring.version>
<spring-data-neo4j.version>3.3.2.RELEASE</spring-data-neo4j.version>
还有一个 SO question 有一个非常相似的问题,但到目前为止没有回应。
这是一件棘手的事情。
您的自定义等于方法 导致两个设置了节点 ID 但尚未设置 uuid-id 的实体相等,以便在将它们加载到集合中时集合将只包含一个。
代码在:RelationshipHelper
protected Set<Object> createEntitySetFromRelationshipEndNodes(Object entity, final MappingPolicy mappingPolicy, final Class<?> relatedType) {
final Iterable<Node> nodes = getStatesFromEntity(entity);
final Set<Object> result = new HashSet<Object>();
for (final Node otherNode : nodes) {
Object target = template.createEntityFromState(otherNode, relatedType, mappingPolicy);
result.add(target);
}
return result;
}
如果您更改代码以在 BasicNode 实体中包含 equals/hashcode:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof BasicNodeEntity)) return false;
BasicNodeEntity that = (BasicNodeEntity) o;
if (nodeId != null) {
if (!nodeId.equals(that.nodeId)) return false;
} else {
if (that.nodeId != null) return false;
}
return true;
}
@Override
public int hashCode() {
return nodeId != null ? nodeId.hashCode() : 0;
}
以便仅设置了 nodeId 的实体具有可比性
并调整子类方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof IdentifiableEntity)) return false;
IdentifiableEntity entity = (IdentifiableEntity) o;
//change
if (!super.equals(o)) return false;
if (id != null) {
if (!id.equals(entity.id)) return false;
} else {
if (entity.id != null) return false;
}
return true;
}
@Override
public int hashCode() {
//change
if (super.hashCode() != 0) return super.hashCode();
return id != null ? id.hashCode() : 0;
}
然后就可以了。
如果您正在使用 Neo4j Server,我建议您查看周五发布的 SDN 4 RC2。
EDIT: Sample project available on github.
我在后端项目中使用 Neo4J(Rest 图形数据库,托管在 grapheneDb 中)和 Spring 数据。
<bean id="graphDatabaseService" class="org.springframework.data.neo4j.rest.SpringCypherRestGraphDatabase">
我在两个实体之间有一个简单的一对多关系:User
和 Stay
。
编辑:我认为这与问题无关,但在 SDN4 中看到 similar problem 后,我认为我需要更新问题(那里是一个基本的 @NodeEntity
class,两个实体都在扩展这个基础 class)。
@NodeEntity
public abstract class BasicNodeEntity implements Serializable {
@GraphId
private Long nodeId;
}
public class User extends BasicNodeEntity {
@RelatedTo(type = "HAS_STAY", direction = Direction.OUTGOING)
Set<Stay> stays;
public void addStay(Stay stay) {
stays.add(stay);
}
}
public class Stay extends BasicNodeEntity {
@RelatedTo(type = "HAS_STAY", direction = Direction.INCOMING)
User user;
}
我无法坚持住超过一次。我添加给用户的第一个停留是正确的,但只是第一个。添加的下一个停留永远不会持续存在,我总是检索第一个。
我创建新住宿的方法是:
@Autowired
Neo4jOperations template;
@Transactional
private void createStay(Stay stay, User user) throws Exception {
stay = template.save(stay);
user.addStay(stay);
template.save(user);
// If i evaluate user at this point, it contains both stays
// But if I retrieve the user from the repository, it just contains
// the first stay, the second one has not persisted.
}
EDIT: 通过UserRepository
.
public interface UserRepositoryCustom {}
public interface UserRepository extends GraphRepository<User>, UserRepositoryCustom {
User findById(String id);
}
User user = userRepository.findById(userId);
注意:我也尝试通过存储库界面而不是 Neo4jTemplate 界面保存,但我遇到了同样的问题。
两个实体都正确保存在 neo4j 数据库中,这只是一个持久性问题。
我认为这应该很容易,所以我可能遗漏了一些东西..
如有任何帮助,我们将不胜感激。
相关版本:
<spring.version>4.0.5.RELEASE</spring.version>
<spring-data-neo4j.version>3.3.2.RELEASE</spring-data-neo4j.version>
还有一个 SO question 有一个非常相似的问题,但到目前为止没有回应。
这是一件棘手的事情。
您的自定义等于方法 导致两个设置了节点 ID 但尚未设置 uuid-id 的实体相等,以便在将它们加载到集合中时集合将只包含一个。
代码在:RelationshipHelper
protected Set<Object> createEntitySetFromRelationshipEndNodes(Object entity, final MappingPolicy mappingPolicy, final Class<?> relatedType) {
final Iterable<Node> nodes = getStatesFromEntity(entity);
final Set<Object> result = new HashSet<Object>();
for (final Node otherNode : nodes) {
Object target = template.createEntityFromState(otherNode, relatedType, mappingPolicy);
result.add(target);
}
return result;
}
如果您更改代码以在 BasicNode 实体中包含 equals/hashcode:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof BasicNodeEntity)) return false;
BasicNodeEntity that = (BasicNodeEntity) o;
if (nodeId != null) {
if (!nodeId.equals(that.nodeId)) return false;
} else {
if (that.nodeId != null) return false;
}
return true;
}
@Override
public int hashCode() {
return nodeId != null ? nodeId.hashCode() : 0;
}
以便仅设置了 nodeId 的实体具有可比性
并调整子类方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof IdentifiableEntity)) return false;
IdentifiableEntity entity = (IdentifiableEntity) o;
//change
if (!super.equals(o)) return false;
if (id != null) {
if (!id.equals(entity.id)) return false;
} else {
if (entity.id != null) return false;
}
return true;
}
@Override
public int hashCode() {
//change
if (super.hashCode() != 0) return super.hashCode();
return id != null ? id.hashCode() : 0;
}
然后就可以了。
如果您正在使用 Neo4j Server,我建议您查看周五发布的 SDN 4 RC2。