【问题标题】:Crashes related to GraphRepository#findAll() when using AspectJ使用 AspectJ 时与 GraphRepository#findAll() 相关的崩溃
【发布时间】:2014-07-18 18:05:42
【问题描述】:

TopLevelTransaction (neo4j-kernel-2.1.2) 中的这一行每次我在通过GraphRepository#findAll() 获得的迭代器上调用next() 时都会抛出NullPointerException

protected void markAsRollbackOnly()
{
    try
    {
        transactionManager.getTransaction().setRollbackOnly(); // NPE here
    }
    catch ( Exception e )
    {
        throw new TransactionFailureException(
            "Failed to mark transaction as rollback only.", e );
    }
}

我发现了一些关于类似崩溃的线程,但堆栈跟踪略有不同。 this question 上公认的解决方案是使用“代理”事务管理,但这似乎是一种创可贴的解决方案。 This question 还提到了“代理”事务管理,并暗示在使用 AspectJ 时 @Transactional 注释可能有问题。

这确实是一个错误,还是我的项目设置不正确?我的代码与standalone hello world 中的代码基本相同,但主类稍微复杂一些:

@Component
public class Test2 {
    @Autowired
    FooRepository repo;

    public static void main(String[] args) {
        AbstractApplicationContext context = new AnnotationConfigApplicationContext("test2");
        Test2 test2 = context.getBean(Test2.class);
        test2.doStuff();
    }

    public void doStuff() {
        createFoo();
        printFoos();
    }

    @Transactional
    public Foo createFoo() {
        Foo foo = new Foo();
        foo.setName("Derp" + System.currentTimeMillis());
        repo.save(foo);
        System.out.println("saved " + foo.toString());
        return foo;
    }

    @Transactional
    public void printFoos() {
        Iterable<Foo> foos = repo.findAll();
        System.out.println("findAll() returned instance of " + foos.getClass().getName());
        Iterator<Foo> iter = foos.iterator();
        System.out.println("iterator is instance of " + iter.getClass().getName());
        if(iter.hasNext()) {
            iter.next(); // CRASHES HERE
        }
    }
}

如果需要,我可以发布我的 POM。

【问题讨论】:

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


    【解决方案1】:

    我没有发现错误。完成这项工作需要两三件事,具体取决于您是要使用代理还是 AspectJ 事务管理。

    首先,必须启用事务管理。由于我使用的是基于注释的配置,因此我通过使用@EnableTransactionManagement 注释我的@Configuration 类来做到这一点。与文档相反,默认模式现在似乎是 AdviceMode.ASPECTJ,而不是 AdviceMode.PROXY

    接下来,您需要确保在事务中使用迭代器。在我的示例中,如果我使用AdviceMode.PROXY,则包含@Autowired 存储库的整个bean 都必须注释@Transactional。如果我使用AdviceMode.ASPECTJ,我可以只注释方法。这是因为使用迭代器对方法的调用是bean内部的自调用,代理事务管理无法拦截和管理内部调用。

    最后,如果您使用AdviceMode.ASPECTJ,则必须按照here 的讨论设置编织。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-18
      • 1970-01-01
      • 1970-01-01
      • 2012-09-10
      • 1970-01-01
      • 2018-03-18
      • 1970-01-01
      相关资源
      最近更新 更多