【发布时间】:2014-08-25 19:22:20
【问题描述】:
在使用 Spring Data Neo4j(使用简单映射模式)时,我偶尔会遇到 NotInTransactionException 被扔进带有 @Transactional 注释的方法中,并且发现自己拔出的头发比我能承受的要多试图诊断这些异常。例如下面的方法:
@Service
public class FooService {
@Autowired Neo4jTemplate template;
//GraphPersisted is an interface containing a single method: Long getId()
//ModelNode is an empty interface implemented by my @NodeEntity classes
@Transactional
public <T extends ModelNode> T getNode(GraphPersisted g, Class<T> clazz){
return template.repositoryFor(clazz).findOne(g.getId()); //NotInTransactionException!!
}
}
正在抛出以下内容:
Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: nested exception is org.neo4j.graphdb.NotInTransactionException
at org.springframework.data.neo4j.support.Neo4jExceptionTranslator.translateExceptionIfPossible(Neo4jExceptionTranslator.java:51)
at org.springframework.data.neo4j.support.Neo4jTemplate.translateExceptionIfPossible(Neo4jTemplate.java:447)
at org.springframework.data.neo4j.support.Neo4jTemplate.getNode(Neo4jTemplate.java:481)
at org.springframework.data.neo4j.repository.NodeGraphRepositoryImpl.getById(NodeGraphRepositoryImpl.java:33)
at org.springframework.data.neo4j.repository.NodeGraphRepositoryImpl.getById(NodeGraphRepositoryImpl.java:24)
at org.springframework.data.neo4j.repository.AbstractGraphRepository.findOne(AbstractGraphRepository.java:127)
at org.springframework.data.neo4j.repository.AbstractGraphRepository.findOne(AbstractGraphRepository.java:51)
at net.mypkg.myapp.core.FooService.getNode(FooService.java:28)
at net.mypkg.myapp.citizenry.BarService.getCitNode(BarService.java:136)
at net.mypkg.myapp.citizenry.BarService.loadCitizens(BarService.java:81)
at net.mypkg.myapp.citizenry.BarService$$FastClassBySpringCGLIB$$792b7a4e.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:640)
at net.mypkg.myapp.citizenry.BarService$$EnhancerBySpringCGLIB$$59949515.loadCitizens(<generated>)
at net.mypkg.myapp.creator.builders.VotingActivityBuilder.makeVotesFor(VotingActivityBuilder.java:46)
at net.mypkg.myapp.creator.builders.VotingActivityBuilder.build(VotingActivityBuilder.java:35)
at net.mypkg.myapp.creator.builders.VotingActivityBuilder$$FastClassBySpringCGLIB$$6871225a.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:640)
at net.mypkg.myapp.creator.builders.VotingActivityBuilder$$EnhancerBySpringCGLIB$$7f5827a1.build(<generated>)
at net.mypkg.myapp.creator.Creator.create(Creator.java:33)
at net.mypkg.myapp.creator.CreatorDriver.run(CreatorDriver.java:52)
at org.springframework.boot.SpringApplication.runCommandLineRunners(SpringApplication.java:634)
... 5 more
我最直接的问题是:为什么会抛出这个异常?为什么我的 @Transactional 注释没有按照我的预期做(即将我对 template.findOne(Long id) 的调用包装在事务中)?
我更大的问题是:你怎么知道?堆栈跟踪中提供了哪些线索可能表明意外行为是从哪里出现的?我对 Spring 和 Spring Data 比较陌生,我确信这些问题本身并不难诊断,我只是在努力这样做,因为我不知道如何解释堆栈跟踪:我应该做什么正在寻找在这些问题出现时诊断这些问题的踪迹?
(请让我知道回答这个问题需要哪些进一步的代码/配置,我会发布它 - 我故意尽可能少地包含,希望你需要什么请参阅诊断此特定问题将帮助我了解 我 需要查看哪些内容以在未来诊断类似的异常。不过,我会说,@Transactional 注释在大型同一应用程序上下文中的其他方法的数量)
【问题讨论】:
-
很难说,但对我来说,您的
FooService似乎没有被代理(不像BarService或VotingActivityBuilder)因此不能用 tx 功能装饰。不过,可能还差得很远。试图重现类似的堆栈跟踪但不能;可能是由于 Spring 版本不同。你的是什么? -
@Hille:很有趣。您是否从以下事实推断出这一点:对
MethodProxy.invoke()的调用与BarService和VotingActivityBuilder方法相关,但与FooService方法无关?你能解释一下这在诊断上告诉我什么吗? PS 我使用的是 SDN 版本 3.1.2(最新稳定版本),它依赖于 Spring Data 版本 1.4.3 -
没错,我查看了堆栈跟踪,并没有看到与
FooService相关的“调用”。另一种判断方法是从上到下查看堆栈跟踪:您在FooService.getNode上运行而没有命中任何代理。 -
是否有任何答案对您的问题有所启发?还有什么不清楚的地方吗?
标签: java spring spring-data spring-data-neo4j