我使用休眠模式来处理与数据库的连接。我有几个连接到不同模式的会话工厂。

在启动时构建所有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永远不可能。我知道问题出在工厂实例变量的static关键字上,构造函数中没有初始化。我不希望这种“永远在线”的初始化!仅在需要时至少初始化一次。

我读了一些设计模式和代码质量书籍,但是我很难实现所学知识。我想我创建了代码气味。如何修复此设计?请说明我的错误以及为什么我的选择值得怀疑。

最佳答案

我不确定编译器警告(可能由IDE发出,而不是javac发出)是否与staticgetFactory()修饰符相关。

实际上,getFactory()实现声明了一个switch语句,该语句的default情况返回null

default:
    assert false : "Switch default should not be reachable.";
    return null;


因此,如果传递的参数不允许在前面的一种情况下输入,则getFactory()确实可能返回null

但是我认为getFactory()的主要问题是缺乏线程安全性。确实,如果有多个线程并发访问它,则可以创建多个会话,并可能生成不一致的状态。
或者,要按需创建会话,可以使用特定样式的单例模式:the initialization-on-demand holder idiom


  在软件工程中,按需初始化持有人(设计
  模式)成语是一个懒惰的单例。在所有版本的Java中,
  该惯用语可实现安全,高度并发的惰性初始化
  很好的表现。

09-25 20:36