使用guice与javafx和hibernate

问题描述 投票:0回答:1

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

public class DictionaryFxController implements Initializable {

    @Inject
    private QueryTemplate queryTemplate;

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

我的application课程看起来像这样

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();
    }

}

我提供Hibernate会话的课程看起来像这样

@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());
    }
}

我把这个类连接到我用来执行查询的template

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();
        }
    }
}

我在模块中绑定了这个类

public class ApplicationModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(QueryTemplate.class);
    }
}

但是当我启动应用程序时,它就失败了

   queryTemplate.insert(langs);

因为queryTemplate是null。问题是什么?

java hibernate javafx-8 guice
1个回答
2
投票

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

您可以通过使用loader.setControllerFactory(...)loader.load(...)反转行的顺序来解决问题。

顺便说一下,设置FXMLLoader的位置比使用load(InputStream)方法更好。如果您使用Stream的方法,则未设置位置,并且位置分辨率将无法在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();
    loader.setLocation(getClass().getResource("/dictionary.fxml"));
    loader.setControllerFactory(injector::getInstance);
    try {
        Parent root = loader.load();
        scene = new Scene(root);
    } catch (IOException e) {
        throw new IllegalStateException(e);
    }

您可以将前两行合并为一行

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

如果你更喜欢。

© www.soinside.com 2019 - 2024. All rights reserved.