【问题标题】:Does Speedment support transactions?Speedment 是否支持交易?
【发布时间】:2018-04-11 10:18:27
【问题描述】:

我已经使用 Speedment 实现了持久层,我想 使用 Spring Boot 单元测试来测试代码。我使用以下注释对我的单元测试进行了注释:

@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class MovieServiceTest {
  ...
}

默认情况下,Spring 将围绕每个测试方法和@Before/@After 回调启动一个新事务,并在最后执行事务的回滚。然而,对于 Speedment,这似乎不起作用。

Speedment 是否支持跨多个调用的事务,如果支持,我必须如何配置 Spring 才能使用 Speedment 事务,或者我必须如何配置 Speedment 才能使用 Spring 提供的数据源?

【问题讨论】:

    标签: speedment


    【解决方案1】:

    AFAIK 它(还没有) - 更正:它似乎为每个流/语句设置一个事务。

    见这篇文章:https://dzone.com/articles/best-java-orm-frameworks-for-postgresql

    但应该可以通过编写自定义扩展来实现:https://github.com/speedment/speedment/wiki/Tutorial:-Writing-your-own-extensions

    编辑:

    根据速度开发人员的说法,一个流映射到一个事务:https://www.slideshare.net/Hazelcast/webinar-20150305-speedment-2

    【讨论】:

      【解决方案2】:

      在 Speedment 3.0.17 中添加了事务支持。但是,它尚未与 Spring @Transactional-annotation 集成,因此您必须将要执行的代码包装为单个事务 like shown here

      txHandler.createAndAccept(tx ->
      
          Account sender = accounts.stream()
              .filter(Account.ID.equal(1))
              .findAny()
              .get();
      
          Account receiver = accounts.stream()
              .filter(Account.ID.equal(2))
              .findAny()
              .get();
      
          accounts.update(sender.setBalance(sender.getBalance() - 100));
          accounts.update(receiver.setBalance(receiver.getBalance() + 100));
      
          tx.commit();
      }
      

      【讨论】:

      • 我刚刚按照描述在我的代码中添加了事务,但是我遇到了java.sql.SQLException:Streaming result set com.mysql.jdbc.RowDataDynamic@8c83ced is still active. No statements may be issued when any streaming result sets are open and in use on a given connection. Ensure that you have called .close() on any active streaming result sets before attempting more queries. 这个问题如何解决?
      • 听起来像一个错误。您应该将其报告给 github.com/speedment/speedment/issues 并添加完整的堆栈跟踪。
      【解决方案3】:

      您很可能正在通过表进行流式传输,然后在流仍处于打开状态时执行更新/删除操作。大多数数据库无法处理在Connection 上打开ResultSet 然后在同一连接上执行更新操作。

      幸运的是,有一个简单的解决方法:考虑在中间 Collection(例如 ListSet)中收集您要修改的实体,然后使用该 Collection 来执行所需的操作操作。

      Speedment 用户指南here 中描述了此案例

      txHandler.createAndAccept(
          tx -> {
             // Collect to a list before performing actions
              List<Language> toDelete = languages.stream()
                  .filter(Language.LANGUAGE_ID.notEqual((short) 1))
                  .collect(toList());
      
              // Do the actual actions
              toDelete.forEach(languages.remover());
      
              tx.commit();
          }
      );
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-08
        • 2017-11-02
        • 2022-11-10
        • 1970-01-01
        • 2013-10-28
        • 2023-03-27
        • 1970-01-01
        • 2010-12-20
        相关资源
        最近更新 更多