Hibernate:迁移到 5.2.14,NPE

Hibernate: migration to 5.2.14, NPE

我将当前的 5.1 休眠设置迁移到新的 5.2.14。我在上下文初始化期间得到 NPE:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'carFactory': Unsatisfied dependency expressed through field 'makeDao'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'makeDAOImpl': Unsatisfied dependency expressed through field 'databaseUtilities'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'databaseUtilities': Unsatisfied dependency expressed through field 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in com.migration.core.config.HibernateConfiguration: Invocation of init method failed; nested exception is java.lang.NullPointerException
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:587)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:91)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:373)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1344)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean[=10=](AbstractBeanFactory.java:312)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:760)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:868)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:409)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:291)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:103)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4861)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5322)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'makeDAOImpl': Unsatisfied dependency expressed through field 'databaseUtilities'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'databaseUtilities': Unsatisfied dependency expressed through field 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in com.migration.core.config.HibernateConfiguration: Invocation of init method failed; nested exception is java.lang.NullPointerException
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:587)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:91)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:373)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1344)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean[=10=](AbstractBeanFactory.java:312)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:251)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1065)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:584)
    ... 24 more
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'databaseUtilities': Unsatisfied dependency expressed through field 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in com.migration.core.config.HibernateConfiguration: Invocation of init method failed; nested exception is java.lang.NullPointerException
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:587)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:91)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:373)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1344)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean[=10=](AbstractBeanFactory.java:312)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:251)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1065)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:584)
    ... 37 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in com.migration.core.config.HibernateConfiguration: Invocation of init method failed; nested exception is java.lang.NullPointerException
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1710)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:583)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean[=10=](AbstractBeanFactory.java:312)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:251)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1065)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:584)
    ... 50 more
Caused by: java.lang.NullPointerException
    at org.hibernate.metamodel.internal.AttributeFactory.getMetaModelType(AttributeFactory.java:202)
    at org.hibernate.metamodel.internal.AttributeFactory.buildPluralAttribute(AttributeFactory.java:176)
    at org.hibernate.metamodel.internal.AttributeFactory.buildAttribute(AttributeFactory.java:82)
    at org.hibernate.metamodel.internal.MetadataContext.wrapUp(MetadataContext.java:213)
    at org.hibernate.metamodel.internal.MetamodelImpl.initialize(MetamodelImpl.java:220)
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:300)
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:460)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:710)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:726)
    at org.springframework.orm.hibernate5.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:535)
    at org.springframework.orm.hibernate5.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:519)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1769)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1706)
    ... 60 more

下面是我的豆子。 HibernateConfiguration.java:

@Configuration
@EnableTransactionManagement
@PropertySource({ "classpath:core.properties" })
@ComponentScan({ "com.migration.core.domain" })
public class HibernateConfiguration {
    private static Logger logger = Logger.getLogger(HibernateConfiguration.class);
    private final static String HIBERNATE_DIALECT = "org.hibernate.dialect.PostgreSQL95Dialect";

    @Autowired private Environment env;
    @Autowired private ResourceLoader resourceLoader;

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
        localSessionFactoryBean.setDataSource(dataSource());
        localSessionFactoryBean.setPackagesToScan(new String[] { "com.migration.core.domain.*" });
        localSessionFactoryBean.setMappingLocations(loadResources());
        localSessionFactoryBean.setHibernateProperties(hibernateProperties());
        return localSessionFactoryBean;
    }

    private Resource[] loadResources() {
        Resource[] resources = null;
        try {
            resources = ResourcePatternUtils.getResourcePatternResolver(resourceLoader)
                    .getResources("classpath:/hibernate/**/*.hbm.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return resources;
    }

    @Bean
    public DataSource dataSource() {
        ComboPooledDataSource сomboPooledDataSource = new ComboPooledDataSource();
        try {
            сomboPooledDataSource.setDriverClass(Preconditions.checkNotNull(env.getProperty("jdbc.driver-class-name")));
        } catch( PropertyVetoException pve ){
            logger.error("Cannot load datasource driver (" + env.getProperty("jdbc.driver-class-name") +"): " + pve.getMessage());
            return null;
        }

        сomboPooledDataSource.setJdbcUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url")));
        сomboPooledDataSource.setUser(Preconditions.checkNotNull(env.getProperty("jdbc.username")));
        сomboPooledDataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.password")));

        сomboPooledDataSource.setMinPoolSize(20);
        сomboPooledDataSource.setMaxPoolSize(50);
        сomboPooledDataSource.setCheckoutTimeout(15);
        сomboPooledDataSource.setMaxStatements(0);
        сomboPooledDataSource.setIdleConnectionTestPeriod(30);

        return сomboPooledDataSource;
    }

    @Bean
    public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) throws Exception{
        HibernateTransactionManager transactionManager = new HibernateTransactionManager();
        transactionManager.setSessionFactory(sessionFactory().getObject());
        return transactionManager;
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
        return new PersistenceExceptionTranslationPostProcessor();
    }

    private static Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.setProperty("hibernate.dialect", HIBERNATE_DIALECT);
        properties.setProperty("hibernate.bytecode.use_reflection_optimizer", "true");
        properties.setProperty("hibernate.show_sql", "false");
        properties.setProperty("hibernate.hbm2ddl.auto", "validate");
        properties.setProperty("hibernate.default_batch_fetch_size", "1000");
        properties.setProperty("hibernate.max_fetch_depth", "2");
        properties.setProperty("hibernate.generate_statistics", "false");
        properties.setProperty("hibernate.default_schema", "EDRIVE");

        properties.setProperty("hibernate.connection.CharSet", "utf8");
        properties.setProperty("hibernate.connection.characterEncoding", "utf8");
        properties.setProperty("hibernate.connection.useUnicode", "true");
        properties.setProperty("hibernate.connection.release_mode", "after_transaction");

        properties.setProperty("hibernate.jdbc.batch_size", "50");
        properties.setProperty("hibernate.jdbc.fetch_size", "500");
        properties.setProperty("hibernate.jdbc.use_scrollable_resultset", "false");

        properties.setProperty("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory");
        properties.setProperty("hibernate.cache.use_query_cache", "true");
        properties.setProperty("hibernate.cache.use_second_level_cache", "true");
        properties.setProperty("hibernate.cache.use_structured_entries", "false");

        properties.setProperty("hibernate.current.session.context.class", "org.springframework.orm.hibernate5.SpringSessionContext");

        return properties;
    }
}

DatabaseUtilities.java:

@Repository
public class DatabaseUtilities {
    static ThreadLocal<Connection> connection = new ThreadLocal<Connection>();
    @Autowired private HibernateConfiguration configuration;

    @Autowired private SessionFactory sessionFactory;

    @Autowired private ApplicationContextProvider contextProvider;
    @Autowired private SequencesDAO sequencesDao;
    @Autowired private LanguageFactory languages;

    // get connection for further use
    public Connection getConnection() {
        if (connection.get() == null) {
            try {
                //loading the database driver
                configuration.dataSource().getConnection();
            } catch (SQLException e) {
                //do something to deal with the error of missing database driver e.g notification to the user.
                e.printStackTrace();
            }
            SessionImplementor session = (SessionImplementor)sessionFactory.openSession();
            connection.set(session.connection());
        }
        return connection.get();
    }

    // get sessionFactory's configuration
    public Configuration getSessionFactoryConfiguration() {
        ApplicationContext context = contextProvider.getApplicationContext();
        LocalSessionFactoryBean sessionFactoryBean = context.getBean("&sessionFactory",LocalSessionFactoryBean.class);
        return sessionFactoryBean.getConfiguration();
    }

    /**
     * Returns a sequence NEXTVAL value
     * @param seqName
     * @return NEXTVAL value
     */
    public long getSequenceNextval( String seqName ) {
        return sequencesDao.getNext(seqName);
    }

    /**
     * Returns Hibernate sessionFactory bean
     * @return SessionFactory
     */
    public SessionFactory getSessionFactory() {
        return this.sessionFactory;
    }

    /**
     * Returns session from the session factory
     */
    public Session getSession() {
        return getSessionFactory().openSession();
    }

    /**
     * Clears current session
     */
    public void clearSession( Session session ) {
        session.clear();
    }

    /**
     * Closes current session
     */
    public void closeSession( Session session ) {
        session.close();
    }

    /**
     * Extracts and converts meta data from the Hibernate's PersistentEntity
     * @param list
     * @return entity
     */
    public List<? extends Entity<Long>> convertMetaData(List<? extends Entity<Long>> list) {
        List<Language> languagesList = languages.getList();
        list.forEach(entity->{
            Map<Language, EntityMetaData> metaData = new HashMap<>();

            // Copy the original package items into the key set
            for (Language key : entity.getMetaData().keySet()) {
                int keyIndex = languagesList.indexOf(key);
                if (keyIndex > -1) { 
                    metaData.put(languagesList.get(keyIndex), entity.getMetaData().get(key));
                }
            }
            entity.setMetaData(metaData);
        });
        return list;
    }

    /**
     * Converts meta data into the HashMap from the PersistentMap 
     * @param <T>
     * @param <T>
     * @param metaData
     * @return HashMap
     */
    @SuppressWarnings("unchecked")
    public <T> Map<Language,EntityMetaData> convertMetaData( T entity ) {
        List<Language> languagesList = languages.getList();
        Map<Language, EntityMetaData> metaData = new HashMap<>();

        // Copy the original package items into the key set
        for (Language key : ((Entity<Long>) entity).getMetaData().keySet()) {
            int keyIndex = languagesList.indexOf(key);
            if (keyIndex > -1) {
                if( ((Entity<Long>) entity).getMetaData().size() > 0 ) {
                    metaData.put(languagesList.get(keyIndex), ((Entity<Long>) entity).getMetaData().get(key));
                } else {
                    metaData.put(languagesList.get(keyIndex), new EntityMetaData());
                }
            }
        }
        return metaData;
    }

    public ReturningWork<Long> callStoredProcedure(Supplier<String> query) {
        ReturningWork<Long> work = ((Connection connection)->{
            try( PreparedStatement preparedStatement = connection.prepareStatement(query.get());
                ResultSet resultSet = preparedStatement.executeQuery(); ) {
                connection.commit();
                resultSet.next();
                return resultSet.getLong(1);
            } catch( SQLException e ) {
                throw e;
            }
        });
        return work;
    }

    @PostConstruct
    public void setupSessionFactory() throws Exception {
        // A SessionFactory is set up once for an application!
        final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
                .configure()
                .build();

        try {
            sessionFactory = new MetadataSources( registry ).buildMetadata().buildSessionFactory();
        } catch (Exception e) {
            // The registry would be destroyed by the SessionFactory, but we had trouble building the SessionFactory
            // so destroy it manually.
            StandardServiceRegistryBuilder.destroy( registry );
        }
    }
}

CarFactory 自动装配 MakeDao,它自动装配 HibernateConfiguration(标准设置)中定义的 SessionFactory。

@Autowired private DatabaseUtilities databaseUtilities;

我不使用 JPA,所以我不需要 EntityManagerFactory - 只需要一个简单的 SessionFactory。另外我想避免使用 XML 进行配置。我的新实施有什么问题?

将您的 sessionFactory 方法更改为:

@Bean
public SessionFactory sessionFactory() {
    LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
    localSessionFactoryBean.setDataSource(dataSource());
    localSessionFactoryBean.setPackagesToScan(new String[] { "com.migration.core.domain.*" });
    localSessionFactoryBean.setMappingLocations(loadResources());
    localSessionFactoryBean.setHibernateProperties(hibernateProperties());
    return localSessionFactoryBean.getObject(); // here is the important change
}

另一种创建 sessionFactory 的方法:

@Bean
public SessionFactory sessionFactory() {
    return new LocalSessionFactoryBuilder(dataSource())
            .scanPackages("com.example.entities")
            //.addFile() this should work for your xml files
            .buildSessionFactory();
}

祝你好运。