dataSource.getConnection在Spring中抛出NullpointerException

时间:2013-02-01 21:48:21

标签: spring

我正在尝试在我的spring应用程序中连接到MySQL数据库。如果我使用DriverManager.getConnection(DB_URL,USER, PASS)但无法与使用bean配置的dataSource建立连接,我可以连接到它。

应用上下文

<bean id="jdbcTest" class="org.springdemo.jdbc.JdbcTest">
  <property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  <property name="url" value="jdbc:mysql://localhost:3306/test"></property>
  <property name="username" value="xxxx"></property>
  <property name="password" value="xxxx"></property>
</bean>

public class JdbcTest {

  private DataSource dataSource;

  public JdbcTest(){
    try {
      Class.forName("com.mysql.jdbc.Driver");
      //conn = DriverManager.getConnection(DB_URL,USER,PASS); This worked!!!!
      conn = dataSource.getConnection(); 
      stmt = conn.createStatement();
    } catch (SQLException e) {
      e.printStackTrace();
    }
  }

  public ResultSet executeQuery(String query){ 
        //executing query; it works as I tested with DriverManager
  }

  public static void main(String[] args) {  
    AbstractApplicationContext context = 
      new ClassPathXmlApplicationContext("spring.xml");
    JdbcTest test = context.getBean("jdbcTest", JdbcTest.class);
    ResultSet rs = test.executeQuery("select * from employee");
    try {
      while(rs.next()){
        System.out.println(rs.getString(1));
      }
    } catch (SQLException e) {
      e.printStackTrace();
    }
  }

}

当我使用DriverManager时,它工作得很好但是,当我使用DataSource对象来获取使用bean配置的连接时,它会给NullPointerException

    Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jdbcTest' defined in class path resource [spring.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springdemo.jdbc.JdbcTest]: Constructor threw exception; nested exception is java.lang.NullPointerException
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1011)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:957)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:490)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:192)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at org.springdemo.DrawingApp.main(DrawingApp.java:21)
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springdemo.jdbc.JdbcTest]: Constructor threw exception; nested exception is java.lang.NullPointerException
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:162)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1004)
    ... 13 more
Caused by: java.lang.NullPointerException
    at org.springdemo.jdbc.JdbcTest.<init>(JdbcTest.java:47)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Unknown Source)
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:147)
    ... 15 more

2 个答案:

答案 0 :(得分:2)

您无法在构造函数中访问dataSource。 Spring首先实例化bean(在你的情况下使用默认构造函数),然后连接属性。

a number of ways来解决这个问题。

构造函数注入

<bean id="jdbcTest" class="org.springdemo.jdbc.JdbcTest">
    <constructor-arg ref="dataSource"/>
</bean>

和班级

public class JdbcTest {
    private DataSource dataSource;

    public JdbcTest(DataSource dataSource) throws SQLException {
        this.dataSource = dataSource;

        conn = dataSource.getConnection(); 
        stmt = conn.createStatement();
    }
}

<强>的InitializingBean

public class JdbcTest implements InitializingBean {
  private DataSource dataSource;

  // setter for dataSource

  public void afterPropertiesSet() {
      // run the actual test
      onn = dataSource.getConnection(); 
      stmt = conn.createStatement();
  }
}

初始化方法

<bean id="jdbcTest" class="org.springdemo.jdbc.JdbcTest" init-method="runTest">
  <property name="dataSource" ref="dataSource"/>
</bean>

和班级

public class JdbcTest {
  private DataSource dataSource;

  // setter for dataSource

  public void runTest() {
      // run the actual test
  }
}

答案 1 :(得分:1)

当使用Spring注入的DataSource时,在调用构造函数之前,DataSource不可用。基本上Spring,由于您的配置,正在执行以下操作:

JdbcTest jdbcTest = new JdbcTest(); // NPE
jdbcTest.setDataSource(dataSource);

你可能想要做的是这样的事情:

JdbcTest jdbcTest = new JdbcTest(dataSource);

为此,请将配置更新为:

<bean id="jdbcTest" class="org.springdemo.jdbc.JdbcTest">
    <constructor-arg ref="dataSource"/>
</bean>

你的JdbcTest类看起来像:

public class JdbcTest {
    private DataSource dataSource;

    pubic JdbcTest(DataSource dataSource) throws SQLException {
        this.dataSource = dataSource;

        conn = dataSource.getConnection(); 
        stmt = conn.createStatement();
    }
}