实体管理器不在JavaFX中工作

我正在使用数据库中的持久性单元和实体类,所有这些都在JavaFx fxml应用程序中,我成功地将所有表作为模型中的实体导入,问题是当我尝试插入实体时出现exception和错误,这是我的整个代码

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

您可以通过为FXMLLoader定义控制器工厂 ,在容器管理的环境中使用FXML控制器(例如,使用InjectionProvider将值注入Afterburner.fx框架中 )。

但实际上,如果刚刚开始使用Java,则不需要进行注入。 在习惯之前,控制内容的反转可能会增加太多魔力。

推荐的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框架集成中演示的更结构化的设计。