【问题标题】:@Transactional: Not committing at end of transaction; using Spring Boot and neo4j@Transactional:事务结束时不提交;使用 Spring Boot 和 neo4j
【发布时间】:2018-10-24 19:30:26
【问题描述】:

我想使用@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-方法时,代码可以完美地提交更改,但并非没有。

配置是通过 Spring Boot 完成的——据我所知,事情应该以这种方式开箱即用(这可能是我出错的部分):

@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().

我希望更改(添加关系)会被提交。我在这里误解了一些东西还是我没有正确配置一些东西?任何帮助将不胜感激,在此先感谢!

更新: 我已按照 cmets 中的建议添加了 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

但是更新仍然没有在数据库中结束 - 有点道理,因为没有创建新关系的查询,但我不明白为什么不:检索到的实体似乎附加到事务,实体得到在事务中修改,因此应在事务完成后提交更改。还是我从根本上误解了这里的一些东西?

【问题讨论】:

  • 不需要将读操作放在事务内部。此外,当您执行多个保存/更新操作并希望保持它们的原子性时,您应该使用事务。
  • 保存方法评论// libraryItemRepository.save(borrowItem);可能是这个原因。
  • 它被评论了,因为我认为@Transactional-method 应该在没有的情况下工作,不是吗?还是我在这里理解错了?
  • 你创建了 Neo4jTransactionManager 的 bean 吗??
  • @Vipul 感谢您的回复 - 我必须这样做吗?我以为 Spring Boot 会处理这种事情? Logging-Output 至少表明正在发生与事务相关的事情......

标签: java spring-boot neo4j spring-data-neo4j


【解决方案1】:

Neo4j-OGM(Spring Data Neo4j 背后的对象图映射器)需要一个显式的save 调用。目前这是通过显式 Spring Data Neo4j save 调用完成的。使用 Spring 的事务边界时没有自动提交。

基本上你的应用程序没有错误,显式保存调用需要取消注释。

关于 cmets 的一些注意事项:您不需要在 Spring Boot 应用程序中自行定义 TransactionManager。 spring-boot-starter-neo4j 负责初始化 Configuration、SessionFactory 和适当的 TransactionManager。

【讨论】:

  • 非常感谢!这解释了很多,解决了我相当头疼的问题。我很想给你+1,但不幸的是我的新帐户似乎还没有资格这样做;我希望我的感谢就足够了:)
猜你喜欢
  • 2021-03-26
  • 2015-04-29
  • 1970-01-01
  • 2021-06-06
  • 1970-01-01
  • 2017-12-11
  • 1970-01-01
  • 2021-09-25
  • 2019-11-25
相关资源
最近更新 更多