多线程中的 PersistenceContext
PersistenceContext in multithreading
出于某种原因,EntityManager 没有被注入到我想在后台保留 运行 的单独线程中。其他 类 可以毫无问题地访问实体管理器,但那些 运行 不在单独的线程中。
我做错了什么?
@Stateful
public class DatabaseManager extends Thread{
@PersistenceContext(unitName="imas-unit")
private EntityManager em;
private int timeBetweenRefresh;
public void run(){
loadProperties();
retrieveDBContent();
long timerTicks = System.currentTimeMillis();
while(running){
if(System.currentTimeMillis() > timerTicks + timeBetweenRefresh){
timerTicks = System.currentTimeMillis();
deleteAllRecords();
retrieveDBContent();
}
Thread.sleep(1000);
}
}
private void deleteAllRecords(){
//Deletes all the records
}
private void loadProperties(){
//Loads properties for methods
}
private void retrieveDBContent(){
List<Cel> celList = methodThatGetsCells();
System.out.println("Saving to database");
for(Cel cell : celList){
try{
em.persist(cell); //Null pointer here
em.flush();
}
catch(Exception e){
System.out.println(e.getMessage());
e.printStackTrace();
}
}
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
System.out.println("Retrieval failed. Please check error log for further information.");
e1.printStackTrace();
}
}
}
如果需要,我可以 post 更多信息。
我觉得你想的有点不对。容器将在它认为完成时取出你的无状态 bean——它不知道你分离了一个线程。
我会考虑使用@Schedule 注释,也许还有@Singleton。看起来您正在定期进行一些数据库维护,并且您可能不希望有多个 bean 这样做。所以更像是:
@Singleton
public class DatabaseManager {
@PersistenceContext(unitName="imas-unit")
private EntityManager em;
...
@Schedule(minute = "*", persistent = false)
private void yourMaintenanceMethod() {
...
在这个例子中,方法 "yourMaintenanceMethod" 每分钟会得到 运行。您可以将秒字段设置为 运行,例如,每 15 秒或任何您需要的时间。
我过去曾成功地将此模式用于类似类型的事情 - 它基本上让容器执行线程并最终稍微简化了您的代码。
出于某种原因,EntityManager 没有被注入到我想在后台保留 运行 的单独线程中。其他 类 可以毫无问题地访问实体管理器,但那些 运行 不在单独的线程中。
我做错了什么?
@Stateful
public class DatabaseManager extends Thread{
@PersistenceContext(unitName="imas-unit")
private EntityManager em;
private int timeBetweenRefresh;
public void run(){
loadProperties();
retrieveDBContent();
long timerTicks = System.currentTimeMillis();
while(running){
if(System.currentTimeMillis() > timerTicks + timeBetweenRefresh){
timerTicks = System.currentTimeMillis();
deleteAllRecords();
retrieveDBContent();
}
Thread.sleep(1000);
}
}
private void deleteAllRecords(){
//Deletes all the records
}
private void loadProperties(){
//Loads properties for methods
}
private void retrieveDBContent(){
List<Cel> celList = methodThatGetsCells();
System.out.println("Saving to database");
for(Cel cell : celList){
try{
em.persist(cell); //Null pointer here
em.flush();
}
catch(Exception e){
System.out.println(e.getMessage());
e.printStackTrace();
}
}
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
System.out.println("Retrieval failed. Please check error log for further information.");
e1.printStackTrace();
}
}
}
如果需要,我可以 post 更多信息。
我觉得你想的有点不对。容器将在它认为完成时取出你的无状态 bean——它不知道你分离了一个线程。
我会考虑使用@Schedule 注释,也许还有@Singleton。看起来您正在定期进行一些数据库维护,并且您可能不希望有多个 bean 这样做。所以更像是:
@Singleton
public class DatabaseManager {
@PersistenceContext(unitName="imas-unit")
private EntityManager em;
...
@Schedule(minute = "*", persistent = false)
private void yourMaintenanceMethod() {
...
在这个例子中,方法 "yourMaintenanceMethod" 每分钟会得到 运行。您可以将秒字段设置为 运行,例如,每 15 秒或任何您需要的时间。
我过去曾成功地将此模式用于类似类型的事情 - 它基本上让容器执行线程并最终稍微简化了您的代码。