Spring @Transactional和Neo4j OGM session.getTransaction()

ale*_*oid 1 neo4j spring-transactions spring-data-neo4j spring-data-neo4j-4 neo4j-ogm

Spring org.springframework.transaction.annotation.Transactional注释和Neo4j OGM org.neo4j.ogm.session.Session.getTransaction()方法之间的相关性是什么?

我正在尝试通过session.getTransaction()Spring注释的方法内部访问当前事务@Transactional但始终为null.

我在Spring MVC RestController方法中添加了以下代码:

Transaction tx = session.beginTransaction();
try {
        for (int i = 0; i < 10; i++) {
            initializeNode(node);
        }
    }
    tx.commit();
} catch (Throwable th) {
    logger.error("Error while inserting mock data", th);
    th.printStackTrace();
} finally {
    tx.close();
}
Run Code Online (Sandbox Code Playgroud)

在以下方法的情况下:

private void initializeNode(TestNode node) {
    System.out.println(session.getTransaction());
}
Run Code Online (Sandbox Code Playgroud)

它打印当前的tx - 到目前为止一切都还可以.

但是在以下方法的情况下:

private void initializeNode(TestNode node) {
    System.out.println(session.getTransaction());

    User admin = userDao.findByUsername("admin");
}
Run Code Online (Sandbox Code Playgroud)

第一次打印当前tx然后null ...事务在提交之前由于某种原因消失..

这是findByUsername方法:

@Service
@Transactional
public class UserDaoImpl implements UserDao {

    @Override
    @Transactional(readOnly = true)
    public User findByUsername(String username) {
        return userRepository.findByUsername(username);
    }
...
}
Run Code Online (Sandbox Code Playgroud)

在提交之后,我得到以下异常:

org.neo4j.ogm.exception.TransactionManagerException: Transaction is not current for this thread
    at org.neo4j.ogm.session.transaction.DefaultTransactionManager.commit(DefaultTransactionManager.java:100)
    at org.neo4j.ogm.transaction.AbstractTransaction.commit(AbstractTransaction.java:83)
    at org.neo4j.ogm.drivers.embedded.transaction.EmbeddedTransaction.commit(EmbeddedTransaction.java:77)
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么 ?为什么交易消失了?

小智 6

这个问题有几个问题和主题.我会试着打破它们,希望最终它们都有意义.

从Spring Data Neo4j(4.1.x)的最新版本开始,Spring @Transactional和Neo4j OGM 之间Session.getTransaction()或者Session.beginTransaction()直接调用时没有相关性.

在前两个代码块中,您可以直接完全管理OGM会话生命周期.在这一点上,Spring根本没有涉及,正如你所说的那样,它按预期执行.

在更新的第三个代码块中,您现在希望手动打开的会话可以使用Spring托管DAO.这里会发生什么取决于您使用SDN的Neo4j驱动程序,但主要是因为您的DAO具有@Transactional注释,Spring将拦截该调用并在您手动管理的所有事务上自行启动全新的事务.在这一点上,我们不能对行为做出任何保证,但最简单的解释是说它会出乎意料(再次,取决于使用的驱动程序).

那你怎么解决这个问题呢?

我假设你想要使用Spring Transactions和Spring Data Neo4j.如果是这种情况,您将要从以下开始:

  1. 更改DAO以使用Spring Data Repositories.这为您提供了许多免费的持久性功能,如查找程序,保存,删除等.
  2. @Transactional注释放在要完成的工作单元周围.您可能有一个方法可以调用userRepository.findByUserName(),修改该用户和调用userRepository.save(user).在Web环境中,这通常是某种服务方法.
  3. 删除任何手动启动或结束OGM会话事务的代码.

您可以在此处找到非常短的代码示例,并在此处找到更长的代码示例.

此处还可以找到全面的指南.

在Spring Data Neo4j 4.2.x中,我们希望引入一些更强大和更友好的@Transactional行为,因此请继续发布该更新.