Правильный способ получения транзакций, используя простое сопоставление объектов / графиков Spring Data Neo4j?
Я использую простое отображение объектов / графиков в Spring Data Neo4j 2.0, где я выполняю постоянные операции, используя среду репозитория Spring Data. Я работаю с репозиториями, а не с Neo4jTemplate. Я внедряю репозитории в мои контроллеры Spring Web MVC, и контроллеры вызывают репозитории напрямую. (Нет промежуточного уровня обслуживания - мои операции, как правило, CRUD и запросы поиска.)
Когда я делаю операции чтения, нет никаких проблем. Но когда я делаю операции записи, я получаю "NotInTransactionException". Насколько я понимаю, операции чтения в Neo4j не требуют транзакций, но операции записи требуют.
Каков наилучший способ показать транзакции здесь, если я хочу придерживаться простого OGM? Я хочу использовать @Transactional, но поместить его в различные интерфейсы репозитория не работает. Если я ввожу промежуточный уровень обслуживания между контроллерами и репозиториями, а затем аннотирую служебные компоненты с помощью @Transactional, то это работает, но мне интересно, есть ли более простой способ сделать это. Без Spring Data у меня, как правило, был бы доступ к реализациям DAO (репозитория), поэтому я мог бы комментировать конкретные DAO с помощью @Transactional, если бы я хотел избежать сквозного уровня обслуживания. В Spring Data репозитории генерируются динамически, поэтому это не представляется возможным.
1 ответ
Во-первых, обратите внимание, что транзакционные 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 транзакционный.