繁体   English   中英

使用 Spring Boot JdbcTemplate 获取 java.lang.NullPointerException

[英]Getting a java.lang.NullPointerException with Spring Boot JdbcTemplate

一般信息: Spring Boot 新手,想通过单元测试测试我的 JDBC 连接。 我做了一个简单的类来连接到我的数据库和一个简单的测试类来跟进正确的测试用例。

问题:执行jdbcTemplate.getDataSource().getConnection();时不断收到 java.lang.NullPointerException jdbcTemplate.getDataSource().getConnection(); 我很难理解为什么。 我尝试使用不同的数据库,并确保可以与常规 JDBC 建立连接。 我已经在 Stack Overflow 上提到了许多其他问题,但过去两天我仍然被困在这个问题上,没有任何进展。 我什至尝试使用不同类型的 DataSource 库,但它们都产生相同的结果。

问题:我该如何解决这个问题? 如果有人也能解释为什么会出现这个问题,以及为什么我们需要在企业级别使用 Spring JDBC,那就太好了。


我的代码:

数据库表服务.java

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.vertica.jdbc.DataSource;

@RestController
@RequestMapping("/databaseServices")
public class DatabaseTableService {

    private JdbcTemplate jdbcTemplate;
    private DataSource dataSource;


    public void setDataSource(DataSource dataSource) {
        this.dataSource= dataSource;
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }


    @RequestMapping("/testConnection")
    @ResponseBody
    public boolean canConnectToDB() {
        boolean result;
        try {
            jdbcTemplate.getDataSource().getConnection();
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
            result = false;
        }
        return result;
    }

}


bean.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.company.project"></context:component-scan>

    <mvc:annotation-driven/>

    <bean id="dataSource"
          class="com.vertica.jdbc.DataSource">
        <property name="URL" value="DBURLHERE"/>
        <property name="userID" value="USERIDHERE"/>
        <property name="password" value="PASSWORDHERE"/>
    </bean>






    <bean id="databaseTableService"
          class="com.company.project.services.DatabaseTableService">
        <property name="dataSource" ref="dataSource"></property>
    </bean>


    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>

</beans>

数据库表服务测试.java

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import com.vertica.jdbc.DataSource;


@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = ApplicationController.class)
@WebAppConfiguration
public class DatabaseTableServiceTest {

    @Autowired
    private WebApplicationContext webApplicationContext;

    private JdbcTemplate jdbcTemplate;
    private MockMvc mockMvc;
    DatabaseTableService databaseTableServiceObject;
    DataSource testDataSource = new DataSource();

    @Before
    public void setUp() throws Exception {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
                .build();

        databaseTableServiceObject = new DatabaseTableService();
    }




    @Test
    public void setDataSource() throws Exception {
        databaseTableServiceObject.setDataSource(testDataSource);
    }

    @Test
    public void validateCanConnectToDB() throws Exception {
        Assert.assertTrue(databaseTableServiceObject.canConnectToDB());
    }


    @After
    public void tearDown() throws Exception {
        mockMvc = null;
        databaseTableServiceObject = null;
        testDataSource = null;
    }

}

应用程序控制器.java

import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;


@SpringBootApplication
@ImportResource({"beans.xml"})
@ComponentScan(basePackages = "com.company.project")
public class ApplicationController {

    public static void main(String[] args) throws Exception {

        SpringApplication.run(ApplicationController.class, args);
    }
}

文件夹结构

文件夹结构


Spring 应用上下文信息Spring 应用上下文信息

您正在使用 Spring Boot,接下来非常努力地不使用。 ApplicationController删除beans.xml@ImportResource (顺便说一下,它不是控制器,而是您的实际应用程序,因为您的服务是您的实际控制器)。 还假设您的ApplicationController在同一个包中,您也可以删除@ComponentScan

然后在您的application.properties添加以下内容

spring.datasource.url=<your-url>
spring.datasource.username=<your-username>
spring.datasource.password=<your-password>
spring.datasource.type=com.vertica.jdbc.DataSource

spring.mvc.view.prefix=/WEB-INF/
spring.mvc.view.suffix=.jsp

Spring Boot 将为您创建一个DataSource和一个JdbcTemplate ,因此无需自己创建。 只需@Autowire您班级中的JdbcTemplate

@RestController
@RequestMapping("/databaseServices")
public class DatabaseTableService {

    private final JdbcTemplate jdbcTemplate;

    @Autowired
    public DatabaseTableService(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate=jdbcTeplate;
    }

    @RequestMapping("/testConnection")
    @ResponseBody
    public boolean canConnectToDB() {
        boolean result;
        try {
            jdbcTemplate.getDataSource().getConnection();
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
            result = false;
        }
        return result;
    }
}

现在你的测试,真是一团糟。 您正在使用 Spring 但正在自己做事,因此不确定您要在那里实现什么。

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = ApplicationController.class)
@WebAppConfiguration
public class DatabaseTableServiceTest {

    @Autowired
    private WebApplicationContext webApplicationContext;

    private MockMvc mockMvc;
    private DatabaseTableService databaseTableServiceObject;

    @Before
    public void setUp() throws Exception {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
                .build();
    }

    @Test
    public void setDataSource() throws Exception {
        databaseTableServiceObject.setDataSource(testDataSource);
    }

    @Test
    public void validateCanConnectToDB() throws Exception {
        Assert.assertTrue(databaseTableServiceObject.canConnectToDB());
    }

}

您可以只@Autowired现在完全构建的服务。

最后一点是您的canConnectToDB方法有缺陷。 您正在获取连接但从未返回/关闭它。 因此,在多次调用此方法后,您的应用程序将停止工作,因为连接池将耗尽或您的数据库停止接受连接。

简而言之,使用框架而不是反对/围绕框架。 阅读文档而不是试图破解它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM