每个应用程序创建一个SessionFactory,而不使用静态方法

时间:2014-08-12 19:57:49

标签: spring hibernate

我有一个名为HibernateUtil的辅助类,它创建一个SessionFactory并返回一个会话。该类工作正常,但它会产生模拟问题,因为Mockito不能使用静态方法。

简单的解决方案似乎创建了一个类的实例,除了我需要确保应用程序中只有一个SessionFactory。如果不使用静态方法,我该怎么做?

public class HibernateUtil {

    private static final Log logger = LogFactory.getLog(SessionFactory.class);
    private static final SessionFactory sessionFactory = createSessionFactory();

    private static SessionFactory createSessionFactory() {
            logger.info("createSessionFactory called");
            Configuration configuration = new Configuration().configure();
            StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
            return configuration.buildSessionFactory(builder.build());
    }

    private static SessionFactory getSessionFactory() {
            return sessionFactory;
    }

    public static Session getSession() {
            Session session = null;
            try {
                    session = HibernateUtil.getSessionFactory().getCurrentSession();
                    if (!session.isOpen()) {
                            session = HibernateUtil.getSessionFactory().openSession();
                    }
            } catch (Exception e) {
                    e.printStackTrace();
            }
            return session;
    }

}

编辑:感谢您的回复!我想我会把它叫做一个晚上,并明天早上再次解决这个问题。

3 个答案:

答案 0 :(得分:0)

另一种方法是使用依赖注入,但是通过代码的外观,你不会这样做。 您可以使用Spring或其他IoC容器来执行IoC ...或diy-di

另一个替代方案(虽然有点hacky)是拥有相同的“静态”接口,但委托给另一个可以在测试中替换的对象。默认情况下,后备实现使用Hibernate,在测试中,您可以使用模拟实例替换该实现。

答案 1 :(得分:0)

如果您不想使用spring hibernate支持,可以将课程更改为:

package com.captain.oh.captain

@Component // singletonbean
public class HibernateUtil {

    private static final Log logger = LogFactory.getLog(SessionFactory.class);
    private SessionFactory sessionFactory;

    @PostConstruct
    private void createSessionFactory() {
            logger.info("createSessionFactory called");
            Configuration configuration = new Configuration().configure();
            StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
            sessionFactory = configuration.buildSessionFactory(builder.build());
    }

    private SessionFactory getSessionFactory() {
            return sessionFactory;
    }

    public Session getSession() {
            Session session = null;
            try {
                    session = HibernateUtil.getSessionFactory().getCurrentSession();
                    if (!session.isOpen()) {
                            session = HibernateUtil.getSessionFactory().openSession();
                    }
            } catch (Exception e) {
                    e.printStackTrace();
            }
            return session;
    }

}

autowire在另一个组件(@Autowired HibernateUtil)中。不要忘记将软件包(com.captain.oh.captain)添加到您的扫描包中(application-context.xml@Configuration类)

另请注意,您的getSession方法不是Thread-safe

答案 2 :(得分:0)

不要直接在代码中使用HibernateUtil,而是将其隐藏在界面后面:

public interface HibernateSessionProvider() {
     Session getSession();
}

使用默认实现:

public class DefaultHibernateSessionProvider() implements HibernateSessionProvider {
     @Override
     public Session getSession() {
         return HibernateUtil.getSession();
     }          
}

然后你可以在测试期间模拟HibernateSessionProvider。这种方法可以使用或不使用Sprting的依赖注入。