Правильный способ получения транзакций, используя простое сопоставление объектов / графиков 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 транзакционный.

Другие вопросы по тегам