簡體   English   中英

實體管理器在JavaFX中不起作用

[英]Entity Manager not working in 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

通過為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.fxairhacks-control框架或(更重量級的) javafx / jpa / spring框架集成中展示的更結構化的設計。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM