如何删除代码气味:getSessionFactory,仅在必要时创建SessionFactory

时间:2018-06-12 20:08:42

标签: java hibernate oop design-patterns factory

我使用hibernate来处理与DB的连接。我有几个会话工厂连接到不同的模式。

在启动时构建所有SessionFactory至少需要60秒。所以我只在必要时才建造它们:

public class HibernateUtil {
    private static SessionFactory factory_db1;
    private static SessionFactory factory_db2;
    //...

    public enum DbSchema {
      db1, db2 //...
    }        

    private createSessionFactory(Configuration conf){
    //...
    }

    public static SessionFactory getFactory(DbSchema dbSchema) {

      try {
        switch (dbSchema) {
            case db1:
                if (factory_db1== null){
                    Configuration conf = new Configuration().configure(HIBERNATE_CFG_DB1);
                    factory_db1= createSessionFactory(conf);
                }
                return factory_db1;
            case db2:
                if (factory_db2 == null){
                    Configuration conf = new Configuration().configure(HIBERNATE_CFGXML_DB2);
                    factory_ooarchive = createSessionFactory(conf);
                }
                return factory_ooarchive;
            //... more factories created
            default:
                assert false : "Switch default should not be reachable.";
                return null;
        }
      } catch (Throwable ex) {
        log.error("Failed to initialize SessionFactory." + ex);
        throw new ExceptionInInitializerError(ex);
    }
}

现在我访问这家工厂时:

Session session = HibernateUtil.getFactory(db1).openSession();
// **Compiler warning: method invocation may produce java.lang.nullpointerexception**

只能通过getFactory()方法获得工厂,因此我认为NPE永远不可能。我知道问题是工厂实例变量的静态关键字,并且在构造函数中没有启动。我不希望这个"永远在线"动初始化!它只应在需要时至少初始化一次。

我阅读了一些设计模式和代码质量书,但我很难实现我学到的东西。我想我创造了一种代码味道。我该如何修复这个设计?请解释我的错误以及为什么我的选择有问题。

1 个答案:

答案 0 :(得分:1)

我不确定编译器警告(可能由IDE发出而不是javac)与static的{​​{1}}修饰符相关。

实际上getFactory()实现声明了一个getFactory()语句,其switch个案例返回default

null

如果传递的参数不允许输入之前的一个案例,那么default: assert false : "Switch default should not be reachable."; return null; 可能确实返回getFactory()

但我认为null的主要问题是缺乏线程安全性。实际上,如果多个线程同时访问它,您可能会创建多个会话并可能生成不一致的状态 或者,要按需创建会话,您可以使用单一模式的特定风格:the initialization-on-demand holder idiom

  

在软件工程中,按需初始化持有者(设计   成语是一个懒惰的单身人士。在所有版本的Java中,   这个习惯用于实现安全,高度并发的延迟初始化   表现不错。