Java 使用SessionFactory时,事务管理在neo4j omg中不起作用

Java 使用SessionFactory时,事务管理在neo4j omg中不起作用,java,spring-boot,spring-transactions,spring-data-neo4j,Java,Spring Boot,Spring Transactions,Spring Data Neo4j,我编写了一个小型Spring引导应用程序,它使用Spring-Boot-starter-data-neo4j连接到一个neo4j实例 我想通过Cypher查询执行一些更新,但在使用SessionFactory打开会话时无法使事务管理工作。通过Neo4jRepository使用OGM注释的实体,事务管理工作正常 出于测试目的,我编写了两个简单的服务,用@Transactional注释: 使用OGM注释类和一个Neo4jRepository: @服务 @交易的 公共类OgmServiceImpl实现

我编写了一个小型Spring引导应用程序,它使用
Spring-Boot-starter-data-neo4j
连接到一个neo4j实例

我想通过Cypher查询执行一些更新,但在使用
SessionFactory
打开
会话时无法使事务管理工作。通过
Neo4jRepository
使用OGM注释的实体,事务管理工作正常

出于测试目的,我编写了两个简单的服务,用
@Transactional
注释:

使用OGM注释类和一个
Neo4jRepository

@服务
@交易的
公共类OgmServiceImpl实现OgmService{
私人最终个人储存库个人储存库;
公共OgmServiceImpl(PersonRepository PersonRepository){
this.personRepository=personRepository;
}
@凌驾
公共存储数据(){
保存(新的人(“杰克”);
如果(真){
抛出新的非法状态异常();
}
保存(新人(“吉尔”);
}
}
在执行storeData()方法时,Jack和Jill都不会保存到Neo4j。一切正常

另一个服务通过在Neo4j
会话上执行Cypher查询来执行相同的操作:

@服务
@交易的
公共类CypherServiceImpl实现CypherService{
私人最终会议工厂会议工厂;
公共CypherServiceImpl(SessionFactory SessionFactory){
this.sessionFactory=sessionFactory;
}
@凌驾
公共存储数据(){
Session Session=sessionFactory.openSession();
query(“CREATE(p:Person{name:'Jack'})”,Map.of();
如果(真){
抛出新的非法状态异常();
}
query(“CREATE(p:Person{name:'Jill'})”,Map.of();
}
}
但是,事务管理失败,因为Jack存储在Neo4j中

对我来说,这种行为是完全出乎意料的。我可以通过显式启动事务来实现事务管理,但这不是我喜欢的方式:

public void storeData(){
Session Session=sessionFactory.openSession();
try(事务tx=session.beginTransaction()){
query(“CREATE(p:Person{name:'Jack'})”,Map.of();
如果(真){
抛出新的非法状态异常();
}
query(“CREATE(p:Person{name:'Jill'})”,Map.of();
tx.commit();
}
}
我是否需要自己配置
SessionFactory
以使其正常工作?为什么Spring Boot不能解决这个问题呢?

只是看了一下。根据文档,当您以编程方式调用
SessionFactory#openSession
时,将创建一个全新的会话,该会话不一定在
@Transactional
注释指定的事务范围内

为了进一步确保这一点,您可以尝试使用以下代码检查断言错误:

@Override
public void storeData() {
    Session session = sessionFactory.openSession();
    assert session.getTransaction() != null;

    session.query("CREATE (p:Person { name: 'Jack' })", Map.of());       
    session.query("CREATE (p:Person { name: 'Jill'})", Map.of());
} 
这将导致断言错误。与hibernate不同的是,我找不到neo4J ogm的方法来实现它

下面编写的代码之所以有效,是因为即使您正在创建一个全新的会话,事务也由您管理。这里您创建的是一个自管理事务,而不是Spring容器管理的事务,尽管这通常不是一个好主意

public void storeData() {
    Session session = sessionFactory.openSession();
    try (Transaction tx = session.beginTransaction()) {
        session.query("CREATE (p:Person { name: 'Jack' })", Map.of());
        if (true) {
            throw new IllegalStateException();
        }
        session.query("CREATE (p:Person { name: 'Jill'})", Map.of());
        tx.commit();
    }
}

您是否尝试将
sessionFactory.openSession()
更改为
sessionFactory.getCurrentSession()
?neo4j ogm sessionFactory实际上不提供这种方法。不过谢谢你的建议:)我也找不到一个方法来获得当前会话。这是我必须处理的事情:)