我在Spring Data Neo4j 2.0中使用简单的对象/图映射,在这里我使用Spring Data存储库框架执行持久性操作。我使用的是存储库,而不是Neo4jTemplate。我将存储库注入到SpringWebMVC控制器中,控制器直接调用repos。(没有中间服务层——我的操作通常是CRUD和finder查询。)
当我进行读取操作时,没有任何问题。但当我写操作时,我会得到"NotInTransactionException"。我的理解是,Neo4j中的读操作不需要事务,但写操作需要事务。
假设我想坚持使用简单的OGM,那么让交易进入画面的最佳方式是什么?我想使用@Transactional,但把它放在各种存储库接口上是行不通的。如果我在控制器和存储库之间引入一个中间服务层,然后用@Transactional注释服务bean,那么它是有效的,但我想知道是否有更简单的方法。如果没有Spring Data,我通常可以访问DAO(存储库)实现,因此,如果我想避免传递服务层,我可以用@Transactional注释具体的DAO。有了Spring Data,repos是动态生成的,所以这似乎不是一个选项。
首先,请注意,拥有事务性DAO通常不是一个好的做法。但是,如果您没有服务层,那么让它位于DAO上。
然后,您可以启用声明性事务。我是这样做的:
首先,定义一个名为@GraphTransactional
:的注释
@Retention(RetentionPolicy.RUNTIME)
@Transactional("neo4jTransactionManager")
public @interface GraphTransactional {
}
更新:spring-data-neo4j添加了这样一个注释,因此您可以重用它,而不是创建一个新的注释:@Neo4jTransactional
然后,在applicationContext.xml
中,有以下内容(其中neo4jdb
是您的EmbeddedGraphDatabase
):
<bean id="neo4jTransactionManagerService"
class="org.neo4j.kernel.impl.transaction.SpringTransactionManager">
<constructor-arg ref="neo4jdb" />
</bean>
<bean id="neo4jUserTransactionService" class="org.neo4j.kernel.impl.transaction.UserTransactionImpl">
<constructor-arg ref="neo4jdb" />
</bean>
<bean id="neo4jTransactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="neo4jTransactionManagerService" />
<property name="userTransaction" ref="neo4jUserTransactionService" />
</bean>
<tx:annotation-driven transaction-manager="neo4jTransactionManager" />
请记住,如果您也使用另一个事务管理器,则必须为这个注释驱动的定义指定order="2"
,还请记住,若您有一个方法同时声明为sql和neo4j transactional,则不会有两阶段提交。