簡體   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