实体管理器在JavaFX中不起作用 [英] Entity Manager not working in JavaFX

查看:168
本文介绍了实体管理器在JavaFX中不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在JavaFx fxml应用程序中都使用了数据库中的Persistence单元和Entity类,我成功将所有表作为实体导入到Model中,问题是当我尝试插入到表中时出现异常和错误一个实体,这是我的整个代码

 public class SampleController implements Initializable {
     @PersistenceContext(unitName="RawdaPU")
     private EntityManager em;

     @FXML
     private Label label;

     @FXML
     private void handleButtonAction(ActionEvent event)
     {
         Moyendidactique moyenDidactique = new Moyendidactique("1", "moyen1", "Type1");
         em.persist(moyenDidactique);
         em.close();
     }

     @Override
     public void initialize(URL url, ResourceBundle rb)
     {
         // TODO
     }     
}

这是按下按钮时(触发handleButtonAction时)出现的全部错误

java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1440)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:69)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:28)
    at javafx.event.Event.fireEvent(Event.java:171)
    at javafx.scene.Node.fireEvent(Node.java:6863)
    at javafx.scene.control.Button.fire(Button.java:179)
    at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:193)
    at com.sun.javafx.scene.control.skin.SkinBase$4.handle(SkinBase.java:336)
    at com.sun.javafx.scene.control.skin.SkinBase$4.handle(SkinBase.java:329)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:64)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:33)
    at javafx.event.Event.fireEvent(Event.java:171)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3324)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3164)
    at javafx.scene.Scene$MouseHandler.access$1900(Scene.java:3119)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1559)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2261)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:228)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:528)
    at com.sun.glass.ui.View.notifyMouse(View.java:922)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:29)
    at com.sun.glass.ui.win.WinApplication$2$1.run(WinApplication.java:67)
    at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1435)
    ... 41 more
Caused by: java.lang.NullPointerException
    at rawda.Controller.SampleController.handleButtonAction(SampleController.java:37)
    ... 46 more

在已经存在的类似问题中我找不到答案,无法确切知道我的缺失,在此先感谢您的帮助.

解决方案

为什么在代码中出现NullPointerException

@PersistenceContext 注释表示依赖关系在容器管理的EntityManager及其关联的持久性上下文上."

默认情况下,FXML控制器不是容器管理的,这意味着它们将不会设置容器管理的成员,例如那些标有@PersistenceContext的成员.

您可以通过定义控制内容反转可能会增加太多的魔力,除非您习惯了.

推荐的JavaFX集成方法供JPA初学者尝试

相反,不要依赖@PersistenceContext批注.直接从实体管理器工厂参考中获取实体管理器.在java2s示例创建示例中,有一个很好的示例在容器管理的环境之外使用EntityManager.从实体管理器查询.

在您的应用程序中提供一种获取实体管理器的机制:

public class SampleApplication extends Application {
  static private EntityManagerFactory emf;
  static {
    try {
      emf = Persistence.createEntityManagerFactory("RawdaPU");
    } catch (Exception e) {
      System.out.println("Fatal: Unable to create entity manager factory");
      e.printStackTrace();
    }  
  }

  static public EntityManager createEntityManager() {
    return emf.createEntityManager();
  }

  @Override 
  public void start(Stage stage) {
    . . .
  }
}

在您的控制器中,从应用程序中获取一个实体管理器,并根据需要使用它.

class SampleController implements Initializable {
  @FXML
  private Label label;

  @FXML 
  private void handleButtonAction(ActionEvent event) {
    EntityManager em = SampleApplication.createEntityManager();
    Moyendidactique moyenDidactique = new Moyendidactique("1", "moyen1", "Type1");
    em.persist(moyenDidactique);
    em.close();
  }

  @Override
  public void initialize(URL location, ResourceBundle resources) {}
}

关于关闭和实体管理器的生命周期

因为您的原始示例在persist语句之后关闭了实体管理器,所以我将实体管理器的创建移到了与close方法相同的方法中,以便它们被匹配.关闭表示实体管理器无法再次使用,因此您也可以在关闭它的同一位置创建它-这样一来,您就不会错误地在其他地方重用它.请注意,您不需要这样做就可以关闭,并且可以根据需要重复使用实体管理器,但是对于jpa入门,只需按照此示例中的说明进行操作就可以了,您可以研究更复杂的实体管理器随着您对技术有了更多的经验和信心,可以重用场景.

并发问题

您还需要了解应用程序中JPA使用的并发集成.直接在按钮的动作处理程序中执行诸如JPA调用之类的操作通常不是一个好主意,因为这些调用阻塞了I/O,这将暂停JavaFX应用程序线程并冻结您的应用程序UI一段时间.相反,最好使用 JavaFX任务和服务并发实用程序处理JPA交互,类似于在 JavaFX JDBC任务示例中从UI线程抽象数据库的工作方式.

对于小型本地数据库而言,并发可能不是什么大问题,因此您可以先尝试将应用程序单线程运行,如果运行良好,那很好,但是如果冻结了,请查看并发实用程序.

后续步骤

上述方法确实是一种快速入门的方法.

一旦您了解了这种简单的方法,您可能希望研究 afterburner中展示的更为结构化的设计. fx airhacks-control 框架或(更重量级的) javafx/jpa/spring框架集成.

I'm using Persistence unit and Entity classes from Database, all in a JavaFx fxml Application, I succeeded importing all my tables as entities in my Model, the proble is that I get an exceptions and errors when I try to insert into an entity, here's my entire code

 public class SampleController implements Initializable {
     @PersistenceContext(unitName="RawdaPU")
     private EntityManager em;

     @FXML
     private Label label;

     @FXML
     private void handleButtonAction(ActionEvent event)
     {
         Moyendidactique moyenDidactique = new Moyendidactique("1", "moyen1", "Type1");
         em.persist(moyenDidactique);
         em.close();
     }

     @Override
     public void initialize(URL url, ResourceBundle rb)
     {
         // TODO
     }     
}

Here is the full errors I get when I press the button (when handleButtonAction is fired)

java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1440)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:69)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:28)
    at javafx.event.Event.fireEvent(Event.java:171)
    at javafx.scene.Node.fireEvent(Node.java:6863)
    at javafx.scene.control.Button.fire(Button.java:179)
    at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:193)
    at com.sun.javafx.scene.control.skin.SkinBase$4.handle(SkinBase.java:336)
    at com.sun.javafx.scene.control.skin.SkinBase$4.handle(SkinBase.java:329)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:64)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:33)
    at javafx.event.Event.fireEvent(Event.java:171)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3324)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3164)
    at javafx.scene.Scene$MouseHandler.access$1900(Scene.java:3119)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1559)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2261)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:228)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:528)
    at com.sun.glass.ui.View.notifyMouse(View.java:922)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:29)
    at com.sun.glass.ui.win.WinApplication$2$1.run(WinApplication.java:67)
    at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1435)
    ... 41 more
Caused by: java.lang.NullPointerException
    at rawda.Controller.SampleController.handleButtonAction(SampleController.java:37)
    ... 46 more

I couldn't find an answer in the already existing similar questions, Can't know exactly what I'm missing, thanks in advance for helping.

解决方案

Why you get a NullPointerException in your code

The @PersistenceContext annotation "Expresses a dependency on a container-managed EntityManager and its associated persistence context."

By default FXML controllers are not container-managed, which means they aren't going to set container-managed members such as those marked with the @PersistenceContext.

You can use FXML controllers in a container-managed environment by defining a controller factory for your FXMLLoader (for example as the InjectionProvider is used to inject values into in the Afterburner.fx framework).

But really, you don't need to do that injection if you are just starting out with Java. The inversion of control stuff likely adds a bit too much magic until you are used to it.

Recommended JavaFX Integration Approach to Try for JPA Beginners

Instead, don't rely on the @PersistenceContext annotation. Get an entity manager directly from an entity manager factory reference. There is a good example of using an EntityManager outside a container managed environment in the java2s sample Create Query From Entity Manager.

In your application provide a mechanism to get an entity manager:

public class SampleApplication extends Application {
  static private EntityManagerFactory emf;
  static {
    try {
      emf = Persistence.createEntityManagerFactory("RawdaPU");
    } catch (Exception e) {
      System.out.println("Fatal: Unable to create entity manager factory");
      e.printStackTrace();
    }  
  }

  static public EntityManager createEntityManager() {
    return emf.createEntityManager();
  }

  @Override 
  public void start(Stage stage) {
    . . .
  }
}

In your controller, get an entity manager from the application and use it as needed.

class SampleController implements Initializable {
  @FXML
  private Label label;

  @FXML 
  private void handleButtonAction(ActionEvent event) {
    EntityManager em = SampleApplication.createEntityManager();
    Moyendidactique moyenDidactique = new Moyendidactique("1", "moyen1", "Type1");
    em.persist(moyenDidactique);
    em.close();
  }

  @Override
  public void initialize(URL location, ResourceBundle resources) {}
}

On Closing and Entity Manager Lifetimes

Because your original example closed the entity manager after the persist statement, I moved the entity manager creation into the same method as the close method so that they are matched. The close means that the entity manager can't be used again, so you may as well create it in the same place that you close it - that way you can't reuse it somewhere else by mistake. Note that you don't need to do the close like that and can reuse the entity manager if you like, but for getting started with jpa, just doing it as in this example answer is likely fine and you can look into more complex entity manager reuse scenarios as you get more experience and confidence with the technology.

Concurrency Concerns

You also need to be aware of concurrency integrations of JPA usage in your application. Doing stuff such as the JPA calls directly in the button's action handler is not usually a great idea because the calls are blocking I/O that will halt the JavaFX application thread and freeze up your application UI for periods of time. Instead, it is best to make use of the JavaFX task and service concurrency utilities to handle JPA interaction similar to how the database work is abstracted from the UI thread in the JavaFX JDBC task sample.

For a small local database it is concurrency is likely not that much of a concern, so you could try your app first single threaded and if it works fine, great, but if it is freezing up then look into the concurrency utilities.

Next Steps

The above approach is really a quick getting started thing.

Once you understand this simple approach, you may want to look into the more structured design demonstrated in the afterburner.fx and airhacks-control frameworks or the (much more heavyweight) javafx/jpa/spring framework integration.

这篇关于实体管理器在JavaFX中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆