JPA和Threads在play框架中

Mau*_*bon 10 multithreading jpa playframework

我正在尝试创建一个多线程服务器.问题是我收到以下错误: play.exceptions.JPAException:JPA上下文未初始化.当在应用程序中找到使用@ javax.persistence.Entity批注注释的一个或多个类时,JPA实体管理器会自动启动.

我要做的是从新线程访问数据库这里是代码

package controllers;
import java.util.Iterator;
import java.util.List;
import models.Ball;


public class MainLoop extends Thread {

@Override
public void run() {
    List<Ball> balls;
    new Ball(5,5,2,2,10,15);
    while (true){
        balls = Ball.all().fetch(); //Here throws an exception 

        for (Iterator iterator = balls.iterator(); iterator.hasNext();) {
            Ball ball = (Ball) iterator.next();
            ball.applyForces();
        }
    }
}
}
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

Ric*_*rdo 13

不要使用纯线程,而是使用job:

@OnApplicationStart 
public class MainLoop extends Job { 
       public void doJob() { 
               new BallJob().now(); 
       }
} 
Run Code Online (Sandbox Code Playgroud)

和BallJob:

public class BallJob extends Job {
public void doJob() {
    List<Ball> balls;
    new Ball(5,5,2,2,10,15);
    while (true){
        balls = Ball.all().fetch(); 
        for (Iterator iterator = balls.iterator(); iterator.hasNext();) {
            Ball ball = (Ball) iterator.next();
            ball.applyForces();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*hut 5

更新

这比下面的更整洁:

JPAPlugin.startTx(false);
// Do your stuff
JPAPlugin.endTx(false);
Run Code Online (Sandbox Code Playgroud)

今天遇到了类似的问题。

您必须EntityManager为每个线程创建新的和事务并将其设置在JPA类中。

Play 用于ThreadLocal将其保留EntityManagerJPA 中,因此对于您创建的线程来说它为空。不幸的是,您不能在JPA 中使用辅助方法来做到这一点(它们是包私有的),您必须ThreadLocal直接使用。以下是您可以这样做的方法:

class Runner extends Runnable {
     @Override
     public void run() {
         if (JPA.local.get() == null) {
             EntityManager em = JPA.newEntityManager();
             final JPA jpa = new JPA();
             jpa.entityManager = em;
             JPA.local.set(jpa);
         }

         JPA.em().getTransaction().begin();
         ... DO YOUR STUFF HERE ...
         JPA.em().getTransaction().commit();
     }
}
Run Code Online (Sandbox Code Playgroud)

我将它与java.util.concurrent 中的单线程执行程序一起使用,没有任何问题。

  • 更新:您可以删除所有 JPA 内容并将其替换为 JPAPlugin.startTx 和 JPAPlugin.closeTx。 (2认同)