简体   繁体   English

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

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

General Information: New to Spring Boot and wanted to test out my JDBC connections via unit tests.一般信息: Spring Boot 新手,想通过单元测试测试我的 JDBC 连接。 I made a simple class to connect to my database and a simple test class to follow up with the proper test case.我做了一个简单的类来连接到我的数据库和一个简单的测试类来跟进正确的测试用例。

Problem: Continuously receiving a java.lang.NullPointerException when performing jdbcTemplate.getDataSource().getConnection();问题:执行jdbcTemplate.getDataSource().getConnection();时不断收到 java.lang.NullPointerException jdbcTemplate.getDataSource().getConnection(); I am having a hard time understanding why.我很难理解为什么。 I tried using different databases, and ensured that I could make a connection with the regular JDBC.我尝试使用不同的数据库,并确保可以与常规 JDBC 建立连接。 I have referred to numerous other questions on Stack Overflow but I have still been stuck on this for the past two days without any progress.我已经在 Stack Overflow 上提到了许多其他问题,但过去两天我仍然被困在这个问题上,没有任何进展。 I even tried to use different types of DataSource libraries but all of them yield the same result.我什至尝试使用不同类型的 DataSource 库,但它们都产生相同的结果。

Question: How do I solve this?问题:我该如何解决这个问题? If anyone can also explain why the issue is happening, and why do we need to use the Spring JDBC on an enterprise level, that would be great.如果有人也能解释为什么会出现这个问题,以及为什么我们需要在企业级别使用 Spring JDBC,那就太好了。


My code:我的代码:

DatabaseTableService.java数据库表服务.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;
    }

} }


beans.xml 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>

DatabaseTableServiceTest.java数据库表服务测试.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;
    }

}

ApplicationController.java应用程序控制器.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);
    }
}

Folder Structure文件夹结构

文件夹结构


Spring Application Context Information Spring 应用上下文信息Spring 应用上下文信息

You are using Spring Boot and next try very hard not to.您正在使用 Spring Boot,接下来非常努力地不使用。 Remove your beans.xml and the @ImportResource from your ApplicationController (which isn't a controller but your actual application btw, as your service is your actual controller).ApplicationController删除beans.xml@ImportResource (顺便说一下,它不是控制器,而是您的实际应用程序,因为您的服务是您的实际控制器)。 Also assuming that your ApplicationController is in the same package you can remove the @ComponentScan as well.还假设您的ApplicationController在同一个包中,您也可以删除@ComponentScan

Then in your application.properties add the following然后在您的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 will create a DataSource and a JdbcTemplate for you, so no need to create that yourself. Spring Boot 将为您创建一个DataSource和一个JdbcTemplate ,因此无需自己创建。 Just @Autowire the JdbcTemplate in your class.只需@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;
    }
}

Now your test, it is quite a mess.现在你的测试,真是一团糟。 You are using Spring but are doing things yourself, so not sure what you are trying to achieve there.您正在使用 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());
    }

}

You can just @Autowired the service which is now fully constructed.您可以只@Autowired现在完全构建的服务。

Final thing is that your canConnectToDB method is flawed.最后一点是您的canConnectToDB方法有缺陷。 You are obtaining a connection but are never returning/closing it.您正在获取连接但从未返回/关闭它。 So after calling this method for a couple of times your application will stop work as the connection pool will be depleted or your database stops accepting connections.因此,在多次调用此方法后,您的应用程序将停止工作,因为连接池将耗尽或您的数据库停止接受连接。

In short work with the framework instead of against/around the framework.简而言之,使用框架而不是反对/围绕框架。 Read the documentation instead of trying to hack your way around it.阅读文档而不是试图破解它。

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

相关问题 Spring Boot 上的 java.lang.NullPointerException - java.lang.NullPointerException on spring boot 在Spring MVC中获取java.lang.NullPointerException - Getting java.lang.NullPointerException in spring mvc java.lang.NullPointerException:使用Spring Boot时为null - java.lang.NullPointerException: null when using Spring Boot JPA在Spring Boot中导致java.lang.NullPointerException - JPA Causing java.lang.NullPointerException in Spring Boot Spring Boot 自动装配服务 java.lang.NullPointerException - Spring Boot autowired service java.lang.NullPointerException 在 spring 启动应用程序中面对 java.lang.NullPointerException - Facing java.lang.NullPointerException in spring boot application 获取 java.lang.NullPointerException - Getting java.lang.NullPointerException 获取java.lang.NullPointerException - Getting java.lang.NullPointerException jdbcTemplate.queryForObject 给出 java.lang.NullPointerException - jdbcTemplate.queryForObject gives java.lang.NullPointerException 奇怪的行为 [Spring boot upgrade 2.2.2]Getting java.lang.NullPointerException: null at org.hibernate.loader.custom.sql.NamedParamBinder.bind - strange behavior [Spring boot upgrade 2.2.2]Getting java.lang.NullPointerException: null at org.hibernate.loader.custom.sql.NamedParamBinder.bind
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM