从 Spring 应用程序中删除 Neo4j 节点
Deleting a Neo4j node from a Spring application
我正在尝试从嵌入图中删除节点。
我使用的是 SDN 3.3。2.RELEASE 我的 Neo4j 是 2.2.4。
但是存储库调用后节点仍然存在:
org.junit.ComparisonFailure: expected:<null> but was:<Manufacturer [name=Siemens]>
这是我的测试:
@Test
public void testDeleteById() {
Neo4JManufacturer loadedManufacturer = neo4JManufacturerRepository.findOne(manufacturer0.getId());
assertThatManufacturer(loadedManufacturer).exists();
neo4JManufacturerRepository.deleteManufacturer(manufacturer0.getId());
assertThatManufacturer(loadedManufacturer).doesNotExist();
}
存储库是:
public interface Neo4JManufacturerRepository extends GraphRepository<Neo4JManufacturer> {
@Transactional
@Query("start u = node({id}) match u-[r]-() delete u,r")
public void deleteManufacturer(@Param("id") Long id);
在尝试使用 deleteManufacturer() 方法删除之前,我尝试使用 delete() 方法删除,如:
neo4JManufacturerRepository.delete(manufacturer0.getId());
但我会得到完全相同的测试失败:
org.junit.ComparisonFailure: expected:<null> but was:<Manufacturer [name=Siemens]>
这是我的节点class:
@NodeEntity
@SequenceGenerator(name = "id_generator", sequenceName = "sq_id_manufacturer")
public class Neo4JManufacturer extends BaseEntity {
@Column(nullable = false, unique = true)
@Indexed
private String name;
public Neo4JManufacturer() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Manufacturer [name=" + name + "]";
}
}
更新:
根据这两条评论,我在 delete 调用之后添加了另一个 find 调用,以触发对数据存储的刷新:
Neo4JManufacturer loadedManufacturer = neo4JManufacturerRepository.findOne(manufacturer0.getId());
assertThatManufacturer(loadedManufacturer).exists();
neo4JManufacturerRepository.delete(manufacturer0.getId());
loadedManufacturer = neo4JManufacturerRepository.findOne(manufacturer0.getId());
assertThatManufacturer(loadedManufacturer).doesNotExist();
而且我还在查询中添加了可选子句:
@Transactional
@Query("START u = node({id}) OPTIONAL MATCH u-[r]-() DELETE u,r")
public void deleteManufacturer(@Param("id") Long id);
现在,我得到一个不同的错误:
No primary SDN label exists .. (i.e one starting with _)
我想我正在尝试删除后的刷新,但由于其他原因失败了?
此外,我想知道使用 JPA 和使用 Neo4j 时刷新和事务处理行为是否相同。实际上,以下 JPA 测试按预期工作:
@Test
public void testDeleteByUserId() {
User loadedUser = userRepository.findOne(user0.getId());
assertThatUser(loadedUser).exists();
loadedUser = userRepository.deleteByUserId(user0.getId());
loadedUser = userRepository.findOne(user0.getId());
assertThatUser(loadedUser).doesNotExist();
}
我的想法是对 Neo4j 数据库做同样的事情。
更新:我现在在事务服务上删除,而不是直接在存储库上删除:
@Modifying
@Transactional(rollbackFor = EntityNotFoundException.class)
@Override
public Neo4JManufacturer delete(Long id) throws EntityNotFoundException {
Neo4JManufacturer manufacturer = findById(id);
if (manufacturer == null) {
throw new EntityNotFoundException();
} else {
neo4jManufacturerRepository.delete(manufacturer.getId());
return manufacturer;
}
}
服务调用如下:
@Test
public void testDeleteById() {
Neo4JManufacturer loadedManufacturer = neo4JManufacturerRepository.findOne(manufacturer0.getId());
assertThatManufacturer(loadedManufacturer).exists();
neo4JManufacturerService.delete(manufacturer0.getId());
Neo4JManufacturer anotherManufacturer = neo4JManufacturerRepository.findOne(manufacturer0.getId());
assertThatManufacturer(anotherManufacturer).doesNotExist();
}
但我仍然遇到同样的异常:
testDeleteById(it.kahoot.robot.data.neo4j.Neo4JManufacturerRepositoryTest) Time elapsed: 0.137 sec <<< ERROR!
org.springframework.dao.InvalidDataAccessApiUsageException: No primary SDN label exists .. (i.e one starting with _) ; nested exception is java.lang.IllegalStateException: No primary SDN label exists .. (i.e one starting with _)
at org.springframework.data.neo4j.support.typerepresentation.LabelBasedNodeTypeRepresentationStrategy.readAliasFrom(LabelBasedNodeTypeRepresentationStrategy.java:136)
at org.springframework.data.neo4j.support.typerepresentation.LabelBasedNodeTypeRepresentationStrategy.readAliasFrom(LabelBasedNodeTypeRepresentationStrategy.java:40)
at org.springframework.data.neo4j.support.mapping.TRSTypeAliasAccessor.readAliasFrom(TRSTypeAliasAccessor.java:36)
at org.springframework.data.neo4j.support.mapping.TRSTypeAliasAccessor.readAliasFrom(TRSTypeAliasAccessor.java:26)
at org.springframework.data.convert.DefaultTypeMapper.readType(DefaultTypeMapper.java:102)
更新 II:我现在有一个测试可以正常通过并且表现符合预期。测试仍然在 @Transactional 注释下。而且它不进行任何手动冲洗。有趣的部分,以及测试停止给出错误的原因:
No primary SDN label exists .. (i.e one starting with _)
是 findById 或 findOne 调用被 findByName 调用所取代。执行 findById 或 findOne 调用会触发上述错误。
这是工作测试的样子:
@Test
public void testIsDelete() {
Neo4JManufacturer loadedManufacturer = neo4JManufacturerRepository.findOne(manufacturer0.getId());
assertThatManufacturer(loadedManufacturer).exists();
neo4JManufacturerRepository.delete(manufacturer0.getId());
loadedManufacturer = neo4JManufacturerService.findByName(loadedManufacturer.getName());
assertThatManufacturer(loadedManufacturer).doesNotExist();
}
存储库 findByName 是:
Neo4JManufacturer findByName(String name);
我有一个记录器,显示 id 设置在 0 以上
DEBUG [Neo4JManufacturerRepositoryTest] ==========>> Id: 4 Name: Siemens
仍然,使用 findById 而不是 findByName 会出现上述错误。
我想知道为什么。
更新三:
我现在已经从测试中删除了事务注释。
这是测试:
@Test
public void testDelete() {
Neo4JManufacturer loadedManufacturer = neo4JManufacturerRepository.findOne(manufacturer0.getId());
assertThatManufacturer(loadedManufacturer).exists();
neo4JManufacturerRepository.delete(manufacturer0.getId());
loadedManufacturer = neo4JManufacturerRepository.findOne(manufacturer0.getId());
assertThatManufacturer(loadedManufacturer).doesNotExist();
assertThatManufacturer(manufacturer0).exists();
manufacturer0 = neo4JManufacturerRepository.save(manufacturer0);
}
控制台显示:
2016-09-01 14:45:57,769 DEBUG [main] c.t.d.n.Neo4JManufacturerRepositoryTest ==========>> Before - Created manufacturer0 - Id: 0
2016-09-01 14:45:58,127 DEBUG [main] c.t.d.n.Neo4JManufacturerRepositoryTest ==========>> After - Deleted manufacturer0 - Id: 0
2016-09-01 14:45:58,320 DEBUG [main] c.t.d.n.Neo4JManufacturerRepositoryTest ==========>> Before - Created manufacturer0 - Id: 4
2016-09-01 14:45:58,850 DEBUG [main] c.t.d.n.Neo4JManufacturerRepositoryTest ==========>> After - Deleted manufacturer0 - Id: 4
2016-09-01 14:45:59,035 DEBUG [main] c.t.d.n.Neo4JManufacturerRepositoryTest ==========>> Before - Created manufacturer0 - Id: 8
Tests run: 4, Failures: 0, Errors: 2, Skipped: 0, Time elapsed: 23.625 sec <<< FAILURE! - in com.thalasoft.data.neo4j.Neo4JManufacturerRepositoryTest
testDelete(com.thalasoft.data.neo4j.Neo4JManufacturerRepositoryTest) Time elapsed: 0.334 sec <<< ERROR!
org.springframework.dao.DataRetrievalFailureException: Node 8 not found; nested exception is org.neo4j.graphdb.NotFoundException: Node 8 not found
它在测试的最后一行源代码上出错,即执行 save() 操作的那一行。
为什么要寻找节点?为什么它抱怨找不到?既然我正在尝试创建它,难道不应该找不到它吗?
由于您的 Cypher 查询正在使用 MATCH u-[r]-()
,如果指定的节点不参与任何关系,它将失败。
您应该改用 OPTIONAL MATCH
,这样即使指定的节点不参与任何关系也能使查询成功:
"START u = node({id}) OPTIONAL MATCH u-[r]-() DELETE u,r"
在同一个 t运行saction 中,节点仍然可见,并且由于您的测试很可能是 @T运行sactional 每个方法,tx 仅在方法完成
参见:http://neo4j.com/docs/stable/transactions-delete.html
如果您在删除后添加 t运行sactional 处理(提交),而没有在测试之上添加 @T运行sactional。您应该再也看不到该节点了。
更新
我运行你的测试,正如我解释的那样。
您的测试(通过它的超类)有一个@T运行sactional 注释,因此测试方法中的所有操作都在 one t[=34 中执行=]saction 然后回滚。
如果您想查看真实世界的行为,则必须在 t运行saction 完成后在它自己的 tx 中进行删除(作为您的服务调用的一部分),节点不再可见.
您的断言还测试了先前加载的节点将为 null,但绝不会出现这种情况,因为作为删除操作的一部分,已经存在的变量不会更改。
我从你的测试超类中删除了全局@T运行sactional 注释并将测试方法更改为:
@Test
public void testDeleteById() {
Neo4JManufacturer loadedManufacturer = neo4JManufacturerRepository.findOne(manufacturer0.getId());
assertThatManufacturer(loadedManufacturer).exists();
neo4JManufacturerService.delete(manufacturer0.getId());
loadedManufacturer = neo4JManufacturerRepository.findOne(manufacturer0.getId());
// both would work
// loadedManufacturer = neo4JManufacturerService.findById(manufacturer0.getId());
assertThatManufacturer(loadedManufacturer).doesNotExist();
}
现在它通过并表现出预期的行为:完成删除的 tx 后,节点消失了。
我正在尝试从嵌入图中删除节点。
我使用的是 SDN 3.3。2.RELEASE 我的 Neo4j 是 2.2.4。
但是存储库调用后节点仍然存在:
org.junit.ComparisonFailure: expected:<null> but was:<Manufacturer [name=Siemens]>
这是我的测试:
@Test
public void testDeleteById() {
Neo4JManufacturer loadedManufacturer = neo4JManufacturerRepository.findOne(manufacturer0.getId());
assertThatManufacturer(loadedManufacturer).exists();
neo4JManufacturerRepository.deleteManufacturer(manufacturer0.getId());
assertThatManufacturer(loadedManufacturer).doesNotExist();
}
存储库是:
public interface Neo4JManufacturerRepository extends GraphRepository<Neo4JManufacturer> {
@Transactional
@Query("start u = node({id}) match u-[r]-() delete u,r")
public void deleteManufacturer(@Param("id") Long id);
在尝试使用 deleteManufacturer() 方法删除之前,我尝试使用 delete() 方法删除,如:
neo4JManufacturerRepository.delete(manufacturer0.getId());
但我会得到完全相同的测试失败:
org.junit.ComparisonFailure: expected:<null> but was:<Manufacturer [name=Siemens]>
这是我的节点class:
@NodeEntity
@SequenceGenerator(name = "id_generator", sequenceName = "sq_id_manufacturer")
public class Neo4JManufacturer extends BaseEntity {
@Column(nullable = false, unique = true)
@Indexed
private String name;
public Neo4JManufacturer() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Manufacturer [name=" + name + "]";
}
}
更新:
根据这两条评论,我在 delete 调用之后添加了另一个 find 调用,以触发对数据存储的刷新:
Neo4JManufacturer loadedManufacturer = neo4JManufacturerRepository.findOne(manufacturer0.getId());
assertThatManufacturer(loadedManufacturer).exists();
neo4JManufacturerRepository.delete(manufacturer0.getId());
loadedManufacturer = neo4JManufacturerRepository.findOne(manufacturer0.getId());
assertThatManufacturer(loadedManufacturer).doesNotExist();
而且我还在查询中添加了可选子句:
@Transactional
@Query("START u = node({id}) OPTIONAL MATCH u-[r]-() DELETE u,r")
public void deleteManufacturer(@Param("id") Long id);
现在,我得到一个不同的错误:
No primary SDN label exists .. (i.e one starting with _)
我想我正在尝试删除后的刷新,但由于其他原因失败了?
此外,我想知道使用 JPA 和使用 Neo4j 时刷新和事务处理行为是否相同。实际上,以下 JPA 测试按预期工作:
@Test
public void testDeleteByUserId() {
User loadedUser = userRepository.findOne(user0.getId());
assertThatUser(loadedUser).exists();
loadedUser = userRepository.deleteByUserId(user0.getId());
loadedUser = userRepository.findOne(user0.getId());
assertThatUser(loadedUser).doesNotExist();
}
我的想法是对 Neo4j 数据库做同样的事情。
更新:我现在在事务服务上删除,而不是直接在存储库上删除:
@Modifying
@Transactional(rollbackFor = EntityNotFoundException.class)
@Override
public Neo4JManufacturer delete(Long id) throws EntityNotFoundException {
Neo4JManufacturer manufacturer = findById(id);
if (manufacturer == null) {
throw new EntityNotFoundException();
} else {
neo4jManufacturerRepository.delete(manufacturer.getId());
return manufacturer;
}
}
服务调用如下:
@Test
public void testDeleteById() {
Neo4JManufacturer loadedManufacturer = neo4JManufacturerRepository.findOne(manufacturer0.getId());
assertThatManufacturer(loadedManufacturer).exists();
neo4JManufacturerService.delete(manufacturer0.getId());
Neo4JManufacturer anotherManufacturer = neo4JManufacturerRepository.findOne(manufacturer0.getId());
assertThatManufacturer(anotherManufacturer).doesNotExist();
}
但我仍然遇到同样的异常:
testDeleteById(it.kahoot.robot.data.neo4j.Neo4JManufacturerRepositoryTest) Time elapsed: 0.137 sec <<< ERROR!
org.springframework.dao.InvalidDataAccessApiUsageException: No primary SDN label exists .. (i.e one starting with _) ; nested exception is java.lang.IllegalStateException: No primary SDN label exists .. (i.e one starting with _)
at org.springframework.data.neo4j.support.typerepresentation.LabelBasedNodeTypeRepresentationStrategy.readAliasFrom(LabelBasedNodeTypeRepresentationStrategy.java:136)
at org.springframework.data.neo4j.support.typerepresentation.LabelBasedNodeTypeRepresentationStrategy.readAliasFrom(LabelBasedNodeTypeRepresentationStrategy.java:40)
at org.springframework.data.neo4j.support.mapping.TRSTypeAliasAccessor.readAliasFrom(TRSTypeAliasAccessor.java:36)
at org.springframework.data.neo4j.support.mapping.TRSTypeAliasAccessor.readAliasFrom(TRSTypeAliasAccessor.java:26)
at org.springframework.data.convert.DefaultTypeMapper.readType(DefaultTypeMapper.java:102)
更新 II:我现在有一个测试可以正常通过并且表现符合预期。测试仍然在 @Transactional 注释下。而且它不进行任何手动冲洗。有趣的部分,以及测试停止给出错误的原因:
No primary SDN label exists .. (i.e one starting with _)
是 findById 或 findOne 调用被 findByName 调用所取代。执行 findById 或 findOne 调用会触发上述错误。
这是工作测试的样子:
@Test
public void testIsDelete() {
Neo4JManufacturer loadedManufacturer = neo4JManufacturerRepository.findOne(manufacturer0.getId());
assertThatManufacturer(loadedManufacturer).exists();
neo4JManufacturerRepository.delete(manufacturer0.getId());
loadedManufacturer = neo4JManufacturerService.findByName(loadedManufacturer.getName());
assertThatManufacturer(loadedManufacturer).doesNotExist();
}
存储库 findByName 是:
Neo4JManufacturer findByName(String name);
我有一个记录器,显示 id 设置在 0 以上
DEBUG [Neo4JManufacturerRepositoryTest] ==========>> Id: 4 Name: Siemens
仍然,使用 findById 而不是 findByName 会出现上述错误。
我想知道为什么。
更新三:
我现在已经从测试中删除了事务注释。
这是测试:
@Test
public void testDelete() {
Neo4JManufacturer loadedManufacturer = neo4JManufacturerRepository.findOne(manufacturer0.getId());
assertThatManufacturer(loadedManufacturer).exists();
neo4JManufacturerRepository.delete(manufacturer0.getId());
loadedManufacturer = neo4JManufacturerRepository.findOne(manufacturer0.getId());
assertThatManufacturer(loadedManufacturer).doesNotExist();
assertThatManufacturer(manufacturer0).exists();
manufacturer0 = neo4JManufacturerRepository.save(manufacturer0);
}
控制台显示:
2016-09-01 14:45:57,769 DEBUG [main] c.t.d.n.Neo4JManufacturerRepositoryTest ==========>> Before - Created manufacturer0 - Id: 0
2016-09-01 14:45:58,127 DEBUG [main] c.t.d.n.Neo4JManufacturerRepositoryTest ==========>> After - Deleted manufacturer0 - Id: 0
2016-09-01 14:45:58,320 DEBUG [main] c.t.d.n.Neo4JManufacturerRepositoryTest ==========>> Before - Created manufacturer0 - Id: 4
2016-09-01 14:45:58,850 DEBUG [main] c.t.d.n.Neo4JManufacturerRepositoryTest ==========>> After - Deleted manufacturer0 - Id: 4
2016-09-01 14:45:59,035 DEBUG [main] c.t.d.n.Neo4JManufacturerRepositoryTest ==========>> Before - Created manufacturer0 - Id: 8
Tests run: 4, Failures: 0, Errors: 2, Skipped: 0, Time elapsed: 23.625 sec <<< FAILURE! - in com.thalasoft.data.neo4j.Neo4JManufacturerRepositoryTest
testDelete(com.thalasoft.data.neo4j.Neo4JManufacturerRepositoryTest) Time elapsed: 0.334 sec <<< ERROR!
org.springframework.dao.DataRetrievalFailureException: Node 8 not found; nested exception is org.neo4j.graphdb.NotFoundException: Node 8 not found
它在测试的最后一行源代码上出错,即执行 save() 操作的那一行。
为什么要寻找节点?为什么它抱怨找不到?既然我正在尝试创建它,难道不应该找不到它吗?
由于您的 Cypher 查询正在使用 MATCH u-[r]-()
,如果指定的节点不参与任何关系,它将失败。
您应该改用 OPTIONAL MATCH
,这样即使指定的节点不参与任何关系也能使查询成功:
"START u = node({id}) OPTIONAL MATCH u-[r]-() DELETE u,r"
在同一个 t运行saction 中,节点仍然可见,并且由于您的测试很可能是 @T运行sactional 每个方法,tx 仅在方法完成
参见:http://neo4j.com/docs/stable/transactions-delete.html
如果您在删除后添加 t运行sactional 处理(提交),而没有在测试之上添加 @T运行sactional。您应该再也看不到该节点了。
更新
我运行你的测试,正如我解释的那样。
您的测试(通过它的超类)有一个@T运行sactional 注释,因此测试方法中的所有操作都在 one t[=34 中执行=]saction 然后回滚。
如果您想查看真实世界的行为,则必须在 t运行saction 完成后在它自己的 tx 中进行删除(作为您的服务调用的一部分),节点不再可见.
您的断言还测试了先前加载的节点将为 null,但绝不会出现这种情况,因为作为删除操作的一部分,已经存在的变量不会更改。
我从你的测试超类中删除了全局@T运行sactional 注释并将测试方法更改为:
@Test
public void testDeleteById() {
Neo4JManufacturer loadedManufacturer = neo4JManufacturerRepository.findOne(manufacturer0.getId());
assertThatManufacturer(loadedManufacturer).exists();
neo4JManufacturerService.delete(manufacturer0.getId());
loadedManufacturer = neo4JManufacturerRepository.findOne(manufacturer0.getId());
// both would work
// loadedManufacturer = neo4JManufacturerService.findById(manufacturer0.getId());
assertThatManufacturer(loadedManufacturer).doesNotExist();
}
现在它通过并表现出预期的行为:完成删除的 tx 后,节点消失了。