昨天突然发现Spring加载Hibernate触发NullPointerException 异常:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/spring-config/spring-hibernate.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerExceptionat org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305)at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
.....
Caused by: java.lang.NullPointerExceptionat org.postgresql.jdbc.TypeInfoCache.getSQLType(TypeInfoCache.java:182)at org.postgresql.jdbc.TypeInfoCache.getSQLType(TypeInfoCache.java:178)at org.postgresql.jdbc.TypeInfoCache.requiresQuoting(TypeInfoCache.java:851)at org.postgresql.jdbc.PgDatabaseMetaData.getTypeInfo(PgDatabaseMetaData.java:2785)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)at java.lang.reflect.Method.invoke(Unknown Source)at org.logicalcobwebs.proxool.ProxyDatabaseMetaData.intercept(ProxyDatabaseMetaData.java:60)at $java.sql.Wrapper$$EnhancerByProxool$$5b0813c3.getTypeInfo(<generated>)at org.hibernate.engine.jdbc.spi.TypeInfo.extractTypeInfo(TypeInfo.java:101)at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:163)at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:111)at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:234)at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:206)at org.hibernate.cfg.Configuration.buildTypeRegistrations(Configuration.java:1885)at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1843)at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1928)at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:372)at org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:454)at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:439)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)... 28 more
感觉相当郁闷,因为不是第一天用啊,这个spring+hibernate的配置一直没问题,后来花了两个小时不断查度娘和google,未果。心有不甘,打开spring-hibernate.xml仔细看:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-4.1.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.1.xsd"> <!-- 配置hibernate的session factory --><bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" destroy-method="destroy"><!-- <bean id="sessionFactory" class="com.freestyle.common.spring.MyLocalSessionFactoryBean" destroy-method="destroy">--><property name="dataSource" ref="dataSource"></property><property name="packagesToScan"> <!-- hibernate sessionFactory管理的类存放位置,自动装载 --><list> <value>com.alco.bms.entities</value> </list> </property><property name="hibernateProperties"><props><prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop><!-- 设置自动创建|更新|验证数据库表结构 --><prop key="hibernate.hbm2ddl.auto">update</prop><!-- 是否在控制台显示sql --><prop key="hibernate.show_sql">true</prop><!-- 是否格式化sql,优化显示 --><prop key="hibernate.format_sql">true</prop><!-- 是否开启二级缓存 --><prop key="hibernate.cache.use_second_level_cache">false</prop><!-- 是否开启查询缓存 --><prop key="hibernate.cache.use_query_cache">false</prop><!-- 数据库批量查询最大数 --><prop key="hibernate.jdbc.fetch_size">100</prop><!-- 数据库批量更新、添加、删除操作最大数 --> <prop key="hibernate.jdbc.batch_size">50</prop><!-- 是否自动提交事务 --><prop key="hibernate.connection.autocommit">false</prop><!-- 指定hibernate在何时释放JDBC连接 --><prop key="hibernate.connection.release_mode">auto</prop><prop key="hibernate.enable_lazy_load_no_trans">false</prop><!-- <prop key="hibernate.use_sql_comments">true</prop>--><prop key="log4j.logger.org.hibernate.type">TRACE</prop></props></property></bean><!-- 配置事务异常封装 --><bean id="persistenceExceptionTranslationPostProcessor"class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" /><!-- 定义事务管理 --><bean id="transactionManager"class="org.springframework.orm.hibernate4.HibernateTransactionManager"><property name="sessionFactory" ref="sessionFactory" /></bean><tx:annotation-driven transaction-manager="transactionManager"/><aop:aspectj-autoproxy proxy-target-class="true"/><context:component-scan base-package="com.alco.bms.dao"/><!-- 定义 Autowired 自动注入 bean --><!-- <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>-->
</beans>
在spring里面配置LocalSessionFactoryBean,也就设置了3个属性,发生NullPointerException应该就这三个其中一个是null值引发的吧,于是写了一个壳MyLocalSessionFactoryBean是extends LocalSessionFactoryBean的,我在新类里面调试一下看传进入的是不是null值:
package com.freestyle.common.spring;import java.util.Properties;import javax.sql.DataSource;import org.springframework.orm.hibernate4.LocalSessionFactoryBean;import com.freestyle.utils.Util;public class MyLocalSessionFactoryBean extends LocalSessionFactoryBean {public void setDataSource(DataSource dataSource){if (dataSource==null){Util.sleep(100);}System.out.println(dataSource);super.setDataSource(dataSource); }public void setPackagesToScan(String ...packagesToScan){if (packagesToScan==null){Util.sleep(100);}System.out.println(packagesToScan);super.setPackagesToScan(packagesToScan);}public void setHibernateProperties(Properties hibernateProperties){if (hibernateProperties==null){Util.sleep(100);}System.out.println(hibernateProperties);super.setHibernateProperties(hibernateProperties);}public MyLocalSessionFactoryBean() {super();// TODO Auto-generated constructor stub}}
将.sleep处都打上断点,将spring-hibernate.xml里面的sessionFactory类换成MyLocalSessionFactoryBean再调试,发现传进来的参数都不为null啊,这下傻了。
后来再看Exception的细节,发现这行:at org.postgresql.jdbc.TypeInfoCache.getSQLType(TypeInfoCache.java:182), 说明可能是数据库或jdbc驱动方面发生的exception,应该与spring/hibernate没关系,于是将proxool.xml数据源切换到另一服务器(两个服务器的database结构一样)再运行,居然没事!!!
这有点不解,最后没招了,只有怀疑jdbc驱动,因为用的是postgresql数据库,服务器是postgresql 9.4 64bit,jdbc驱动用的是postgresql-9.4.1208.jre6.jar,后来上postgresql官网下了postgresql-9.4.1209.jar 换上。 一切OK!!!
开始不相信,于是再换回版本号为1208的jar, 出exception,换1209的jar , OK!!
原来你是这样的PostgreSQL 驱动啊!!!