我正在使用数据库中的持久性单元和实体类,所有这些都在 JavaFx fxml 应用程序中,我成功地将所有表作为模型中的实体导入,问题是当我尝试插入时出现异常和错误一个实体,这是我的整个代码
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 Controller 不是容器管理的,这意味着它们不会设置容器管理的成员,例如用 @PersistenceContext
标记的成员。
您可以通过定义 controller factory 在容器管理的环境中使用 FXML Controller 。对于您的 FXMLLoader(例如 InjectionProvider 用于将值注入(inject)到 Afterburner.fx framework 中)。
但实际上,如果您刚刚开始使用 Java,则不需要执行该注入(inject)。 inversion of control stuff在您习惯之前,可能会添加太多魔力。
推荐 JPA 初学者尝试的 JavaFX 集成方法
相反,不要依赖 @PersistenceContext
注释。直接从实体管理器工厂引用获取实体管理器。 java2s 示例 Create Query From Entity Manager 中有一个在容器管理环境之外使用 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) {
. . .
}
}
在您的 Controller 中,从应用程序获取实体管理器并根据需要使用它。
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 task and service concurrency utilities处理 JPA 交互,类似于 JavaFX JDBC task sample 中从 UI 线程抽象数据库工作的方式。 .
对于小型本地数据库,并发性可能不是那么重要,因此您可以首先尝试单线程应用程序,如果它工作正常,那就太好了,但如果它卡住了,请查看并发实用程序。
后续步骤
上述方法确实是一个快速入门的方法。
一旦您了解了这种简单的方法,您可能想要研究 afterburner.fx 中演示的更加结构化的设计。和 airhacks-control框架或(更重量级)javafx/jpa/spring framework integration .
关于java - 实体管理器在 JavaFX 中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16496448/