Java 使用HK2将hibernate会话注入Jersey

Java 使用HK2将hibernate会话注入Jersey,java,hibernate,dependency-injection,jersey-2.0,hk2,Java,Hibernate,Dependency Injection,Jersey 2.0,Hk2,我正在开发一个小应用程序,在使用DI时遇到了一些问题 我有一个存储库类,用于持久化我的实体,并将其注入到我的服务中。我想使用H2K向它注入会话对象。 为此,我尝试做以下SO帖子中描述的类似事情: 所以我创建了SFFactory类并在ApplicationConfig中注册它 SFFactory.java DefaultMessageRepository 你知道我的解决方案有什么问题吗?是什么导致了这个问题?主要问题: [java.lang.NullPointerException] 查看您

我正在开发一个小应用程序,在使用DI时遇到了一些问题

我有一个存储库类,用于持久化我的实体,并将其注入到我的服务中。我想使用H2K向它注入会话对象。 为此,我尝试做以下SO帖子中描述的类似事情:

  • 所以我创建了SFFactory类并在ApplicationConfig中注册它

    SFFactory.java

    DefaultMessageRepository


    你知道我的解决方案有什么问题吗?是什么导致了这个问题?

    主要问题:

    [java.lang.NullPointerException]

    查看您的存储库类

    @Service
    public class DefaultMessageRepository implements MessageRepository {
    
        @Inject
        private Session session; <-------------------+
                                                     | // You shadow session
        public void saveMessage(Message message) {   |
            Session session = null;   <--------------+
            Transaction tx = null;
            try {
                tx = session.beginTransaction();
            ...
        }
        ...
    }
    
  • 在请求范围内配置
    SFFactory

    @Override
    protected void configure() {
        bindFactory(SFFactory.class)
                .to(Session.class)
                .in(RequestScoped.class);
    }
    
  • 另一个需要解决的问题是,
    SessionFactory
    应该是应用程序中的单个实例。为此,我们可以为它创建一个工厂,并将其注入
    SFFactory
    。比如说

    public class SessionFactoryFactory implements Factory<SessionFactory> {
    
        private final SessionFactory factory;
    
        public SessionFactoryFactory() {
            Configuration configuration = new Configuration();
            configuration.configure("hibernate.cfg.xml");
            StandardServiceRegistryBuilder srBuilder = new StandardServiceRegistryBuilder();
            srBuilder.applySettings(configuration.getProperties());
            factory = configuration.buildSessionFactory(srBuilder.build());
            System.out.println("--- SessionFactory Created ---");
        }
    
        @Override
        public SessionFactory provide() {
            System.out.println("--- SessionFactory Provided ---");
            return factory;
        }
    
        @Override
        public void dispose(SessionFactory factory) {
            factory.close();
        }
    }
    
    SessionFactory sessionFactory =...
    ...
    bind(sessionFactory).to(SessionFactory.class);
    
    您的配置将更改为

    @Override
    protected void configure() {
        bindFactory(SessionFactoryFactory.class)
                .to(SessionFactory.class)
                .in(Singleton.class);
        bindFactory(SFFactory.class)
                .to(Session.class)
                .in(RequestScoped.class);
    }
    

    更新 因此,似乎除了阴影之外,另一个主要问题是OP没有显示的
    MessageRepositoryFactory
    (在github项目中的注释中)

    这样,框架就创建了实例。
    工厂
    实际上应该只在无法以上述方式绑定的情况下使用,例如,您需要进行一些初始化。我们甚至不可能为
    SessionFactoryFactory
    创建
    工厂,而是在其他地方进行所有会话工厂配置,只绑定实例。比如说

    public class SessionFactoryFactory implements Factory<SessionFactory> {
    
        private final SessionFactory factory;
    
        public SessionFactoryFactory() {
            Configuration configuration = new Configuration();
            configuration.configure("hibernate.cfg.xml");
            StandardServiceRegistryBuilder srBuilder = new StandardServiceRegistryBuilder();
            srBuilder.applySettings(configuration.getProperties());
            factory = configuration.buildSessionFactory(srBuilder.build());
            System.out.println("--- SessionFactory Created ---");
        }
    
        @Override
        public SessionFactory provide() {
            System.out.println("--- SessionFactory Provided ---");
            return factory;
        }
    
        @Override
        public void dispose(SessionFactory factory) {
            factory.close();
        }
    }
    
    SessionFactory sessionFactory =...
    ...
    bind(sessionFactory).to(SessionFactory.class);
    

    我们只需绑定一个
    SessionFactory
    singleton。

    感谢您的时间和帮助!但是当我按照你的建议做的时候,我得到了相同的结果——NullPointerException。NullPointerException指向哪一行(代码段)?我已经测试过了,效果很好。只需删除方法本地
    会话
    声明,它就可以正常工作。这个答案的要求是一种改进。您是否尝试删除方法中的会话声明?我向SFFactroy和SessionFactoryFactory添加了System.out.println()语句,似乎从未调用过提供方法。请检查您的Hibernate配置是否良好(无异常)。在独立的主方法上进行测试。如果一切正常,那么上述所有修复都已经过测试。我不知道从那里还能告诉你什么。为了简洁起见,我删除了存储库绑定,但它应该仍然存在。也许那不见了。我不知道谢谢你!这才是真正的问题。现在一切都如我所料。
    public class SessionFactoryFactory implements Factory<SessionFactory> {
    
        private final SessionFactory factory;
    
        public SessionFactoryFactory() {
            Configuration configuration = new Configuration();
            configuration.configure("hibernate.cfg.xml");
            StandardServiceRegistryBuilder srBuilder = new StandardServiceRegistryBuilder();
            srBuilder.applySettings(configuration.getProperties());
            factory = configuration.buildSessionFactory(srBuilder.build());
            System.out.println("--- SessionFactory Created ---");
        }
    
        @Override
        public SessionFactory provide() {
            System.out.println("--- SessionFactory Provided ---");
            return factory;
        }
    
        @Override
        public void dispose(SessionFactory factory) {
            factory.close();
        }
    }
    
    public class SFFactory implements Factory<Session> {
    
        private final SessionFactory factory;
    
        @Inject
        public SFFactory(SessionFactory factory) {
            this.factory = factory;
        }
    
        @Override
        public Session provide() {
            System.out.println("--- Session Created ---");
            return factory.openSession();
        }
    
        @Override
        public void dispose(Session session) {
            if (session.isOpen()) {
                session.close();
            }
        }
    }
    
    @Override
    protected void configure() {
        bindFactory(SessionFactoryFactory.class)
                .to(SessionFactory.class)
                .in(Singleton.class);
        bindFactory(SFFactory.class)
                .to(Session.class)
                .in(RequestScoped.class);
    }
    
    public class MessageRepositoryFactory implements Factory<MessageRepository> {
        @Override
        public MessageRepository provider() {
            return new DefaultMessageRepository();
        }
        ...
    }
    
    bind(DefaultMessageRepository.class).to(MessageRepository.class).in(..);
    
    SessionFactory sessionFactory =...
    ...
    bind(sessionFactory).to(SessionFactory.class);