在javafx和hibernate中使用guice

在javafx和hibernate中使用guice,java,hibernate,javafx-8,guice,Java,Hibernate,Javafx 8,Guice,我有一个javafx控制器,看起来像这样 public class DictionaryFxController implements Initializable { @Inject private QueryTemplate queryTemplate; @SuppressWarnings("unchecked") @Override public void initialize(URL location, ResourceBundle resour

我有一个
javafx
控制器,看起来像这样

public class DictionaryFxController implements Initializable {

    @Inject
    private QueryTemplate queryTemplate;

    @SuppressWarnings("unchecked")
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        ....
        queryTemplate.insert(langs);
        ....
    }
}
public class Main extends Application {

    public static void main(String[] args) throws Exception {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Injector injector = Guice.createInjector(new ApplicationModule());
        Scene scene = null;
        FXMLLoader loader = new FXMLLoader();
        try {
            Parent root = loader.load(getClass().getResourceAsStream("/dictionary.fxml"));
            loader.setControllerFactory(injector::getInstance);
            scene = new Scene(root);
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }

        primaryStage.setTitle("Dictionary");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

}
@Singleton
public class HibernateController {
    private SessionFactory sessionFactory;

    public HibernateController() {
        sessionFactory = new Configuration()
                .configure()
                .buildSessionFactory();
    }

    public Session openSession() {
        return sessionFactory.openSession();
    }

    @PreDestroy
    private void close() {
        sessionFactory.close();
        StandardServiceRegistryBuilder.destroy(sessionFactory.getSessionFactoryOptions().getServiceRegistry());
    }
}
我的
应用程序
类如下所示

public class DictionaryFxController implements Initializable {

    @Inject
    private QueryTemplate queryTemplate;

    @SuppressWarnings("unchecked")
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        ....
        queryTemplate.insert(langs);
        ....
    }
}
public class Main extends Application {

    public static void main(String[] args) throws Exception {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Injector injector = Guice.createInjector(new ApplicationModule());
        Scene scene = null;
        FXMLLoader loader = new FXMLLoader();
        try {
            Parent root = loader.load(getClass().getResourceAsStream("/dictionary.fxml"));
            loader.setControllerFactory(injector::getInstance);
            scene = new Scene(root);
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }

        primaryStage.setTitle("Dictionary");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

}
@Singleton
public class HibernateController {
    private SessionFactory sessionFactory;

    public HibernateController() {
        sessionFactory = new Configuration()
                .configure()
                .buildSessionFactory();
    }

    public Session openSession() {
        return sessionFactory.openSession();
    }

    @PreDestroy
    private void close() {
        sessionFactory.close();
        StandardServiceRegistryBuilder.destroy(sessionFactory.getSessionFactoryOptions().getServiceRegistry());
    }
}
我的类提供了
Hibernate
会话,如下所示

public class DictionaryFxController implements Initializable {

    @Inject
    private QueryTemplate queryTemplate;

    @SuppressWarnings("unchecked")
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        ....
        queryTemplate.insert(langs);
        ....
    }
}
public class Main extends Application {

    public static void main(String[] args) throws Exception {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Injector injector = Guice.createInjector(new ApplicationModule());
        Scene scene = null;
        FXMLLoader loader = new FXMLLoader();
        try {
            Parent root = loader.load(getClass().getResourceAsStream("/dictionary.fxml"));
            loader.setControllerFactory(injector::getInstance);
            scene = new Scene(root);
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }

        primaryStage.setTitle("Dictionary");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

}
@Singleton
public class HibernateController {
    private SessionFactory sessionFactory;

    public HibernateController() {
        sessionFactory = new Configuration()
                .configure()
                .buildSessionFactory();
    }

    public Session openSession() {
        return sessionFactory.openSession();
    }

    @PreDestroy
    private void close() {
        sessionFactory.close();
        StandardServiceRegistryBuilder.destroy(sessionFactory.getSessionFactoryOptions().getServiceRegistry());
    }
}
我将这个类连接到用于生成查询的
模板中

public class QueryTemplate {
    private HibernateController hibernateController;

    @Inject
    public QueryTemplate(HibernateController controller) {
        this.hibernateController = controller;
    }

    public <T> void insert(List<T> objects) {
        try (Session session = hibernateController.openSession()) {
            Transaction tx = session.beginTransaction();

            // generalize
            objects.forEach(session::save);

            tx.commit();
        }
    }
}
但当我启动应用程序时,它在线路上失败了

   queryTemplate.insert(langs);
因为
queryTemplate
为空。
问题是什么?

加载FXML后,您正在设置控制器出厂设置;此时已创建控制器。由于
fxmloader
将使用默认机制创建控制器-即简单地调用控制器的默认构造函数-控制器不由Guice管理,并且不会初始化其注入字段

只需使用
loader.setControllerFactory(…)
loader.load(…)
颠倒行的顺序,即可解决此问题

另外,设置
fxmloader
的位置比使用
load(InputStream)
方法更好。如果使用获取
流的方法
,则不会设置位置,并且在FXML文件中位置解析将无法正常工作

因此,替换

    FXMLLoader loader = new FXMLLoader();
    try {
        Parent root = loader.load(getClass().getResourceAsStream("/dictionary.fxml"));
        loader.setControllerFactory(injector::getInstance);
        scene = new Scene(root);
    } catch (IOException e) {
        throw new IllegalStateException(e);
    }

可以将前两行合并为一行

    FXMLLoader loader = new FXMLLoader(getClass().getResource("/dictionary.fxml"));

如果愿意。

加载FXML后,您正在设置控制器工厂;此时已创建控制器。由于
fxmloader
将使用默认机制创建控制器-即简单地调用控制器的默认构造函数-控制器不由Guice管理,并且不会初始化其注入字段

只需使用
loader.setControllerFactory(…)
loader.load(…)
颠倒行的顺序,即可解决此问题

另外,设置
fxmloader
的位置比使用
load(InputStream)
方法更好。如果使用获取
流的方法
,则不会设置位置,并且在FXML文件中位置解析将无法正常工作

因此,替换

    FXMLLoader loader = new FXMLLoader();
    try {
        Parent root = loader.load(getClass().getResourceAsStream("/dictionary.fxml"));
        loader.setControllerFactory(injector::getInstance);
        scene = new Scene(root);
    } catch (IOException e) {
        throw new IllegalStateException(e);
    }

可以将前两行合并为一行

    FXMLLoader loader = new FXMLLoader(getClass().getResource("/dictionary.fxml"));
如果你愿意的话