我试图同时访问mysql数据库以获取使用F.Promise的对象列表,但我得到:
没有实体经理绑定到此线程
虽然在我调用存储过程的方法中,我用JPA.withTransactionAsync包装它但仍然得到相同的错误。
import play.libs.F.*;
import play.mvc.*;
import java.util.concurrent.Callable;
import static play.libs.F.Promise.promise;
public class Application extends Controller {
public static Promise<Result> index() {
return promise(new Function0<Integer>() {
public Integer apply() {
return getUserId();
}
}).map(new Function<Integer,Result>() {
public Result apply(Integer i) {
return ok("Got " + i);
}
});
并在getUserId()内部
public static int getUserId()
{
return JPA.withTransactionAsync(.........);
}
答案 0 :(得分:2)
这是一个已知问题 - 您可以看到它的讨论here。
引用James Roper ......
跨线程使用事务会引入死锁。这是问题所在:
所以我们陷入僵局。上面的场景描述了一个简单的场景,其中只有一个连接和一个线程,但我们有许多用户在更现实的情况下看到生产死锁,其中许多线程在连接池上被阻塞,并且许多连接保持线程被阻塞等待连接池阻止线程产生。
解决方案是使用异步连接池,不幸的是,JPA不支持。解决方法是使用专用线程池来异步获取连接,这样,当连接池耗尽时,专用线程将阻塞,但这不会影响任何内容(除了可能嵌套尝试获取连接)因为它仅用于从池中获取连接。
所以,你有3个选择:
您可以使用this library正确处理实体管理器的关闭,但仍然可以解决上述死锁问题。
使用JPA.withTransaction
代替JPA.withTransactionAsync
。
使用没有这些问题的Ebean。
编辑:为了完整起见,我将添加选项4(我的首选解决方案),即不使用ORM框架并将其替换为jOOQ。