当前位置: 首页 > 知识库问答 >
问题:

Play Framework 2.5.4异步Hibernate操作

微生高谊
2023-03-14

如何使用Akka在使用Hibernate的db上执行操作而不阻塞web客户端?

结果发现错误是由dao.get()方法引起的。我更改了start()方法,以获取一个实际的对象,而不是数据库中的id,现在没有错误,但没有发生任何事情(如我前面所说,它卡在em.merge()上)。

public CompletionStage<Result> start(SomeObject object) {
    ExecutionContext ec = Akka.system().dispatchers().lookup("akka.actor.db-context");
    return CompletableFuture.supplyAsync(() -> doStuff(object), play.libs.concurrent.HttpExecution.fromThread(ec))
            .thenApply(i -> ok("Got result: " + i));
}

过时:

如果我尝试这样的事情:

@Transactional
public CompletionStage<Result> start(Long id) {
    ExecutionContext ec = Akka.system().dispatchers().lookup("akka.actor.db-context");
    return CompletableFuture.supplyAsync(() -> doStuff(dao.get(id)), play.libs.concurrent.HttpExecution.fromThread(ec))
            .thenApply(i -> ok("Got result: " + i));
}

当我使用下面的代码启动上面的过程时:

@Transactional
public Result mainMethod() {
    List<SomeObject> allObjects= dao.getAll();
    int size = allObjects.size();
    for(int i = 0; i < size; i++) {
        start(allObjects.get(i).getId());
    }
    return ok("Started");
}

那么新创建的线程(Actor)在尝试数据库操作时进入无限循环。

谢谢!

尝试使用:

ExecutionContext ec = Akka.system().dispatchers().lookup("akka.actor.db-context");
return CompletableFuture.supplyAsync(() -> jpa.withTransaction("default", true, ()-> doStuff(dao.get(id))), play.libs.concurrent.HttpExecution.fromThread(ec))
                .thenApply(i -> ok("Got result: " + i));

我得到了同样的错误。

共有1个答案

闽高峯
2023-03-14

@Transactional注释位于同步方法上。我想您需要一个异步块内的事务。您可以使用for jpa方法withTransaction代替注释。其签名(来自Play java api)

/**
 * Run a block of code in a JPA transaction.
 *
 * @param name The persistence unit name
 * @param readOnly Is the transaction read-only?
 * @param block Block of code to execute
 * @param <T> type of result
 * @return code execution result
 */
public <T> T withTransaction(String name, boolean readOnly, Supplier<T> block);

应该是这样的:

>

  • 在控制器中注入JPAApi:

    @Inject
    JPAApi jpa;
    

    通过对JPA的调用实现异步执行器:

     jpa.withTransaction("default", true, ()->doStuff(dao.get(id)), play.libs.concurrent.HttpExecution.fromThread(ec))
        .thenApply(i -> ok("Got result: " + i)));
    

    注意对withTransaction的调用中的第二个参数true用于只读操作(在您的例子中)。

  •  类似资料:
    • 概述 定时器 Promise 对象

    • 下面的这些操作符属于单独的rxjava-async模块,它们用于将同步对象转换为Observable。 start( ) — 创建一个Observable,它发射一个函数的返回值 toAsync( ) or asyncAction( ) or asyncFunc( ) — 将一个函数或者Action转换为已Observable,它执行这个函数并发射函数的返回值 startFuture( ) — 将

    • 单线程模型 单线程模型指的是,JavaScript 只在一个线程上运行。也就是说,JavaScript 同时只能执行一个任务,其他任务都必须在后面排队等待。 注意,JavaScript 只在一个线程上运行,不代表 JavaScript 引擎只有一个线程。事实上,JavaScript 引擎有多个线程,单个脚本只能在一个线程上运行(称为主线程),其他线程都是在后台配合。 JavaScript 之所以采

    • 默认情况下playbook中的任务执行时会一直保持连接,直到该任务在每个节点都执行完毕.有时这是不必要的,比如有些操作运行时间比SSH超时时间还要长. 解决该问题最简单的方式是一起执行它们,然后轮询直到任务执行完毕. 你也可以对执行时间非常长(有可能遭遇超时)的操作使用异步模式. 为了异步启动一个任务,可以指定其最大超时时间以及轮询其状态的频率.如果你没有为 poll 指定值,那么默认的轮询频率是

    • 我在单元测试(用C#编写)中存根了必要的方法等,但问题是在断言测试之前异步操作没有完成。 我怎么才能绕过这个?我应该创建一个模拟TaskFactory或任何其他技巧来单元测试异步操作吗?

    • 我有一个Primeface应用程序,其中我启动了一个包含表单的对话框。对话框有一个保存/取消按钮对。在这个对话框中,我无法调用on完成、onstart等方法。我在其他回复中看到原因是没有执行AJAX。但是,我不知道这种情况下的原因,因为命令按钮的类型是提交,并且应该有ajax="true"(默认情况下)。有人能在里面放一点光吗? 我的xhtml: 这是我的后盾: 谢谢!