为什么在代码中得到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框架集成中展示的更结构化的设计。



