0

データベースの永続ユニットとエンティティ クラスをすべて 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

既存の同様の質問で答えが見つかりませんでした。不足しているものを正確に知ることができません。助けてくれてありがとう。

4

1 に答える 1

4

コードで NullPointerException が発生する理由

@PersistenceContextアノテーションは、「コンテナー管理の EntityManager とそれに関連付けられた永続コンテキストへの依存関係を表現します。」

デフォルトでは、FXML コントローラーはコンテナー管理ではありません。つまり、@PersistenceContext.

FXMLLoader のコントローラー ファクトリを定義することにより、コンテナー管理環境で FXML コントローラーを使用できます (たとえば、InjectionProviderを使用してAfterburner.fx フレームワークに値を注入します)。

しかし実際には、Java を使い始めたばかりであれば、その注入を行う必要はありません。コントロールの反転は、慣れるまで少し魔法がかかりすぎる可能性があります。

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) {
    . . .
  }
}

コントローラーで、アプリケーションからエンティティ マネージャーを取得し、必要に応じて使用します。

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 呼び出しなどをボタンのアクション ハンドラで直接実行することは、通常は良い考えではありません。呼び出しによって I/O がブロックされ、JavaFX アプリケーション スレッドが停止し、アプリケーション UI が一定期間フリーズするからです。代わりに、 JavaFX JDBC タスク サンプルでデータベース作業が UI スレッドから抽象化される方法と同様に、 JavaFX タスクおよびサービス同時実行ユーティリティを利用して JPA 対話を処理することをお勧めします。

小規模なローカル データベースの場合、同時実行性はそれほど重要ではない可能性が高いため、アプリを最初にシングル スレッドで試してみて、問題なく動作する場合は問題ありませんが、フリーズしている場合は同時実行ユーティリティを調べてください。

次のステップ

上記のアプローチは、本当にすぐに始められるものです。

この単純なアプローチを理解したら、afterburner.fx および airhacks-control フレームワーク、または (はるかに重い) javafx/jpa/spring フレームワーク統合 で示されている、より構造化された設計を検討すること勧めます

于 2013-05-11T12:42:27.210 に答える