javax.naming.Reference 与 org.hibernate.SessionFactory 不兼容

javax.naming.Reference incompatible with org.hibernate.SessionFactory

我在 Websphere 8.5.5.4 上使用 hibernate-core-4.2.21.Final

Hibernate配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
                                         "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
 <session-factory name="mySessionFactory">

    <property name="hibernate.hbm2ddl.auto">update</property>
    <property name="hibernate.show_sql">false</property>
    <property name="hibernate.format_sql">true</property>
    <property name="hibernate.connection.datasource">MyDS</property>
    <property name="hibernate.default_schema">dbo</property>
    <property name="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</property>
    <property name="hibernate.connection.autocommit">false</property>
    <property name="hibernate.jndi.class">com.ibm.websphere.naming.WsnInitialContextFactory</property>


    <property name="hibernate.jndi.url">corbaloc::myapp-prod-fnicn1.my.com:2809,:myapp-prod-FNICN2.my.com:2809,:myapp-prod-fnicn1.my.com:2811,:myapp-prod-FNICN2.my.com:2811,:myapp-prod-fnicn1.my.com:2812,:myapp-prod-FNICN2.my.com:2812</property> 

    <property name="hibernate.transaction.auto_close_session">true</property>
    <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
    <property name="hibernate.transaction.flush_before_completion">true</property>

    <property name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.WebSphereExtendedJTATransactionLookup</property>

    <property name="hibernate.current_session_context_class">jta</property>
    <property name="jta.UserTransaction">java:comp/UserTransaction</property>

  <mapping resource="gov/mci/efada/entities/User.hbm.xml"/>

 </session-factory>
</hibernate-configuration>

我如何配置 Hibernate:

Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
        serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
                .buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);

我如何获得会话工厂:

sessionFactory = (SessionFactory) new InitialContext().lookup("mySessionFactory");

有时,对 SessionFactory 的查找会抛出:

javax.naming.Reference incompatible with org.hibernate.SessionFactory

我通过如下制作单例 class 解决了这个问题:

public class EntityHome {

    protected static final Log log = LogFactory.getLog(EntityHome.class);
    protected SessionFactory sessionFactory;
    private static ServiceRegistry serviceRegistry;
    private static EntityHome entityHome;

    public static EntityHome getInstance() {
        if (entityHome == null) {
            try {
                entityHome = new EntityHome();
            } catch (Exception e) {
                AppLogger.log("########### unable to configure hibernate,exception is: " + e.getMessage());
                entityHome = null;
            }
        }
        return entityHome;
    }

    private EntityHome() throws Exception {
        try {
            configureHibernate();
        } catch (Exception e) {
            throw e;
        }
    }

    private void configureHibernate() throws HibernateException {

        Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
        serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
                .buildServiceRegistry();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
    }

    public SessionFactory getSessionFactory() throws NamingException {
        if (sessionFactory == null || sessionFactory.isClosed()) {
            configureHibernate();
        }
        return sessionFactory;
    }

    public UserTransaction getTransaction() {

        UserTransaction transaction = null;

        try {
            Object o = new InitialContext().lookup("java:comp/UserTransaction");
            transaction = (UserTransaction) o;
            return transaction;
        } catch (Exception e) {
            throw new IllegalStateException("Could not locate java:comp/UserTransaction in JNDI");
        }
    }

    public static <T> List<T> fromSetToList(Set<T> set) {
        List<T> list = new ArrayList<T>();
        for (T o : set) {
            list.add(o);
        }
        return list;
    }
}

在每个 DAO class 中,我调用单例 class 如下:

public class CarCategoryHome {

        private final SessionFactory sessionFactory = getSessionFactory();

        protected SessionFactory getSessionFactory() {
            try {
                return EntityHome.getInstance().getSessionFactory();
            } catch (NamingException e) {
                AppLogger.Log(e);
                return null;
            }
        }

        public CarCategory findById(Integer id) {
            try {
                CarCategory instance = (CarCategory) sessionFactory.getCurrentSession()
                        .get("com.myapp.data.CarCategory", id);
                return instance;
            } catch (RuntimeException re) {
                throw re;
            }
        }

    }