@Transactional: не совершать в конце транзакции;используя Spring Boot и neo4j - PullRequest
0 голосов
/ 24 октября 2018

Я хотел использовать @Transactional, ожидая, что аннотированные методы получат отдельную транзакцию, которая будет зафиксирована в конце метода.

Однако, если я проверю БД, ничего не было зафиксировано:

@Transactional
public boolean borrowLibraryItem(Long libraryUserId, Long uniqueLibraryItemNumber) {
    boolean success = false;
    LibraryUser borrower = libraryUserRepository.findByLibraryUserId(libraryUserId);
    LibraryItem borrowItem = libraryItemRepository.findByUniqueLibraryItemNumber(uniqueLibraryItemNumber);
    success = borrower != null && borrowItem != null;
    if (success) {
        BorrowedByRel borrowedByRel = new BorrowedByRel(borrower, borrowItem);
        borrowedByRel.setBorrowDate(LocalDateTime.now());
        borrowItem.setBorrowedByRel(borrowedByRel);
        // libraryItemRepository.save(borrowItem);
    }
    return success;
}

Код прекрасно фиксирует изменения при использовании repository.save -метода, но не без него.

Конфигурирование выполняется с помощью пружинной загрузки - насколько я понял, все должно работать «из коробки» таким образом (возможно, это та часть, где я ошибся):

@SpringBootApplication
@EnableNeo4jRepositories(basePackages = "yalms.libraryapi.repositories")
@EntityScan("yalms.libraryapi.entities")
@EnableTransactionManagement
public class YalmsLibraryApplication {
    public static void main(String[] args) {
        SpringApplication.run(YalmsLibraryApplication.class, args);
    }
}

Кажется, что-то происходит с транзакциями, как показывает следующее logging.level.org.springframework.transaction.interceptor=TRACE:

Getting transaction for borrowLibraryItem()..
Don't need to create transaction for findByLibraryUserId, not transactional..
Request: MATCH (n:`LibraryUser`)..
Don't need to create transaction for findByUniqueLibraryItemNumber, not transactional..
Request: MATCH (n:`LibraryItem`)..
Completing transaction for borrowLibraryItem().

Я ожидаю, что изменения (добавление отношений) будут зафиксированы.Я что-то здесь неправильно понимаю или у меня что-то не так настроено, верно?Любая помощь будет очень признательна, спасибо заранее!

ОБНОВЛЕНИЕ: Я добавил Neo4jTransactionManager -Bean, как предложено в комментариях, к сожалению, это не помогло решитьмоя проблема:

    @Bean
    public SessionFactory sessionFactory() {
        org.neo4j.ogm.config.Configuration configuration = new org.neo4j.ogm.config.Configuration.Builder()
                .uri(databaseUrl)
                .credentials(userName, password)
                .build();
        return new SessionFactory(configuration,"yalms.libraryapi");
    }

    @Bean
    public Neo4jTransactionManager transactionManager() {
        return new Neo4jTransactionManager(sessionFactory());
    }

Я включил трассировку для всего, что исходит от spring.data.*, и это меня довольно удивляет, так как кажется, что все работает нормально:

TRACE 19634 --- [nio-8080-exec-2] .s.t.s.TransactionSynchronizationManager : Initializing transaction synchronization
TRACE 19634 --- [nio-8080-exec-2] o.s.t.i.TransactionInterceptor           : Getting transaction for [yalms.libraryapi.services.BorrowService.borrowLibraryItem]
TRACE 19634 --- [nio-8080-exec-2] o.s.t.i.TransactionInterceptor           : Don't need to create transaction for [org.springframework.data.neo4j.repository.support.SimpleNeo4jRepository.findByLibraryUserId]: This method isn't transactional.
DEBUG 19634 --- [nio-8080-exec-2] .s.d.n.r.q.d.DerivedGraphRepositoryQuery : Executing query for method findByLibraryUserId
TRACE 19634 --- [nio-8080-exec-2] .s.t.s.TransactionSynchronizationManager : Retrieved value [org.springframework.data.neo4j.transaction.SessionHolder@4adaed6] for key [org.neo4j.ogm.session.SessionFactory@5f4fecd0] bound to thread [http-nio-8080-exec-2]
 INFO 19634 --- [nio-8080-exec-2] o.n.o.drivers.bolt.request.BoltRequest   : Request: MATCH (n:`LibraryUser`) WHERE n.`libraryUserId` = { `libraryUserId_0` } WITH n RETURN n,[ [ (n)<-[r_b1:`BORROWED_BY`]-(l1:`LibraryItem`) | [ r_b1, l1 ] ] ], ID(n) with params {libraryUserId_0=0}
TRACE 19634 --- [nio-8080-exec-2] o.s.t.i.TransactionInterceptor           : Don't need to create transaction for [org.springframework.data.neo4j.repository.support.SimpleNeo4jRepository.findByUniqueLibraryItemNumber]: This method isn't transactional.
DEBUG 19634 --- [nio-8080-exec-2] .s.d.n.r.q.d.DerivedGraphRepositoryQuery : Executing query for method findByUniqueLibraryItemNumber
TRACE 19634 --- [nio-8080-exec-2] .s.t.s.TransactionSynchronizationManager : Retrieved value [org.springframework.data.neo4j.transaction.SessionHolder@4adaed6] for key [org.neo4j.ogm.session.SessionFactory@5f4fecd0] bound to thread [http-nio-8080-exec-2]
 INFO 19634 --- [nio-8080-exec-2] o.n.o.drivers.bolt.request.BoltRequest   : Request: MATCH (n:`LibraryItem`) WHERE n.`uniqueLibraryItemNumber` = { `uniqueLibraryItemNumber_0` } WITH n RETURN n,[ [ (n)-[r_b1:`BORROWED_BY`]->(l1:`LibraryUser`) | [ r_b1, l1 ] ] ], ID(n) with params {uniqueLibraryItemNumber_0=2}
TRACE 19634 --- [nio-8080-exec-2] o.s.t.i.TransactionInterceptor           : Completing transaction for [yalms.libraryapi.services.BorrowService.borrowLibraryItem]
TRACE 19634 --- [nio-8080-exec-2] o.s.d.n.t.Neo4jTransactionManager        : Triggering beforeCommit synchronization
TRACE 19634 --- [nio-8080-exec-2] o.s.d.n.t.Neo4jTransactionManager        : Triggering beforeCompletion synchronization
DEBUG 19634 --- [nio-8080-exec-2] o.s.d.n.t.Neo4jTransactionManager        : Initiating transaction commit
DEBUG 19634 --- [nio-8080-exec-2] o.s.d.n.t.Neo4jTransactionManager        : Committing Neo4j OGM transaction [org.neo4j.ogm.drivers.bolt.transaction.BoltTransaction@5a5172dc] on Session [org.neo4j.ogm.session.Neo4jSession@7dc575ae]
TRACE 19634 --- [nio-8080-exec-2] o.s.d.n.t.Neo4jTransactionManager        : Triggering afterCommit synchronization
TRACE 19634 --- [nio-8080-exec-2] .s.t.s.TransactionSynchronizationManager : Clearing transaction synchronization
TRACE 19634 --- [nio-8080-exec-2] o.s.d.n.t.Neo4jTransactionManager        : Triggering afterCompletion synchronization
DEBUG 19634 --- [nio-8080-exec-2] o.s.d.n.t.Neo4jTransactionManager        : Not closing pre-bound Neo4j Session after transaction
TRACE 19634 --- [nio-8080-exec-2] .s.t.s.TransactionSynchronizationManager : Removed value [org.springframework.data.neo4j.transaction.SessionHolder@4adaed6] for key [org.neo4j.ogm.session.SessionFactory@5f4fecd0] from thread [http-nio-8080-exec-2]
DEBUG 19634 --- [nio-8080-exec-2] o.s.d.n.w.s.OpenSessionInViewInterceptor : Closed Neo4j OGM Session in OpenSessionInViewInterceptor

Но обновление все еще не заканчивается в БД - имеет смысл, так как нет запроса, который создает новое отношение, но я не понимаю, почему нет: кажется, что извлеченные сущности присоединены к транзакции, сущности получаютизменен внутри транзакции, поэтому изменения должны быть зафиксированы после завершения транзакции.Или я что-то здесь неправильно понял принципиально?

1 Ответ

0 голосов
/ 05 ноября 2018

Neo4j-OGM (средство отображения графов объектов за Spring Data Neo4j) нуждается в явном вызове save.В настоящее время это выполняется явным вызовом Spring Data Neo4j save.При использовании транзакционной границы Spring автоматическая фиксация не выполняется.

По сути, в вашем приложении нет ошибок, и явный вызов сохранения необходимо оставлять без комментариев.

Некоторые примечания к комментариям:Вам не нужно определять TransactionManager самостоятельно в приложениях Spring Boot.spring-boot-starter-neo4j заботится об инициализации Configuration, SessionFactory и соответствующих TransactionManager.

...