我使用spring task定时读取数据库,但是老是报空指针异常,断点调试显示jdbctemplate为空,但是我在controller里调用这个方法就正常,很诧异

解决方案 »

  1.   

    首先应该确定jdbctemplate是否注入(注解/xml配置)
    其次确定持有jdbctemplate句柄的对象是否spring管理下(有注解/xml配置)
    再次确定持有jdbctemplate句柄的类是否在spring扫描路径之下
      

  2.   

    @Repository
    public class DataDao {
    private final Log logger = LogFactory.getLog(this.getClass());
    @Autowired
    private JdbcTemplate jdbcTemplate;

    private JsonUtils utils = new JsonUtils(); public JdbcTemplate getJdbcTemplate() {
    return jdbcTemplate;
    } public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
    this.jdbcTemplate = jdbcTemplate;
    } public String getExtraMonitor_RTelnet() {
    String sql = "SELECT * FROM T_EXTRAMONITOR_INFO WHERE EMTYPE = 2";
    return utils.listToJson(jdbcTemplate.queryForList(sql));
    }
    }<!-- bean annotation driven -->
    <context:annotation-config />
    <context:component-scan base-package="com.tds.extramonitor.*">
    </context:component-scan> <context:property-placeholder location="/WEB-INF/conf/extramonitor.properties"
    ignore-unresolvable="true" />
    <bean id="dataSourceC3p0" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="oracle.jdbc.driver.OracleDriver"></property>
    <property name="jdbcUrl" value="${jdbc.url}"></property>
    <property name="user" value="${jdbc.username}"></property>
    <property name="password" value="${jdbc.password}"></property>
    <!-- 初始化连接池中的连接数,取值应在minPoolSize与maxPoolSize之间,默认为3 -->
    <property name="initialPoolSize" value="10"></property>
    <!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。默认值: 0 -->
    <property name="maxIdleTime" value="30"></property>
    <!--连接池中保留的最大连接数。默认值: 15 -->
    <property name="maxPoolSize" value="100"></property>
    <!-- 连接池中保留的最小连接数,默认为:3 -->
    <property name="minPoolSize" value="10"></property>
    <!--c3p0全局的PreparedStatements缓存的大小。如果maxStatements与maxStatementsPerConnection均为0,则缓存不生效,只要有一个不为0,则语句的缓存就能生效。如果默认值: 
    0 -->
    <property name="maxStatements" value="200"></property>
    <!-- 当连接池连接耗尽时,客户端调用getConnection()后等待获取新连接的时间,超时后将抛出SQLException,如设为0则无限期等待。单位毫秒。默认: 
    0 -->
    <property name="checkoutTimeout" value="3000"></property>
    <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。默认值: 3 -->
    <property name="acquireIncrement" value="2">
    </property>
    <!--定义在从数据库获取新连接失败后重复尝试的次数。默认值: 30 ;小于等于0表示无限次 -->
    <property name="acquireRetryAttempts" value="0">
    </property>
    <!--重新尝试的时间间隔,默认为:1000毫秒 -->
    <property name="acquireRetryDelay" value="1000"></property>
    <!--关闭连接时,是否提交未提交的事务,默认为false,即关闭连接,回滚未提交的事务 -->
    <property name="autoCommitOnClose" value="false"></property>
    <!--如果为false,则获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常,但是数据源仍有效保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。默认: 
    false -->
    <property name="breakAfterAcquireFailure" value="false"></property>
    <!--每60秒检查所有连接池中的空闲连接。默认值: 0,不检查 -->
    <property name="idleConnectionTestPeriod" value="60"></property>
    <!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。默认值: 0 -->
    <!-- <property name="maxStatementsPerConnection"></property> -->
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <constructor-arg ref="dataSourceC3p0" />
    </bean>
    <task:annotation-driven scheduler="qbScheduler"
    mode="proxy" />
    <task:scheduler id="qbScheduler" pool-size="10" />@Component("taskJob")
    public class RegulerMonitor {
    @Scheduled(cron = "0/10 * * * * ?")
    public void job1() {
    Monitor monitor = new Monitor();
    DataDao dao = new DataDao(); monitor.RTelnetMonitor(dao.getExtraMonitor_RTelnet());
    }
    } java.lang.NullPointerException
    at com.tds.extramonitor.dao.DataDao.getExtraMonitor_RTelnet(DataDao.java:85)
    at com.tds.extramonitor.bo.RegulerMonitor.job1(RegulerMonitor.java:15)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65)
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
    at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
      

  3.   

    @Autowired
    private JdbcTemplate jdbcTemplate;DataDao dao = new DataDao();
    dao.set(jdbcTemplate);
      

  4.   

    DataDao也应该注入而不是new出来
    @Autowired
    private DataDao dataDao;