一般信息: Sprint启动新手,希望通过单元测试测试我的JDBC连接。我创建了一个简单的类来连接到我的数据库和一个简单的测试类来跟进正确的测试用例。
问题:执行jdbcTemplate.getDataSource().getConnection();
时连续收到java.lang.NullPointerException我很难理解原因。我尝试使用不同的数据库,并确保我可以与常规JDBC建立连接。我已经提到了Stack Overflow上的许多其他问题,但过去两天我仍然坚持这个问题而没有任何进展。我甚至尝试使用不同类型的DataSource库,但它们都产生相同的结果。
问题:如何解决此问题?如果有人也可以解释为什么会出现问题,为什么我们需要在企业级别上使用Spring JDBC,那就太好了。
我的代码:
DatabaseTableService.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
<?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
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
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);
}
}
文件夹结构
答案 0 :(得分:1)
你正在使用Spring Boot,接下来很努力不去。从您的beans.xml
移除@ImportResource
和ApplicationController
(这不是一个控制器,但实际应用程序是btw,因为您的服务是您的实际控制器)。另外,假设您的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
方法存在缺陷。您正在获取连接,但永远不会返回/关闭它。因此,在调用此方法几次后,您的应用程序将停止工作,因为连接池将耗尽或您的数据库停止接受连接。
简而言之,使用框架而不是反对/围绕框架。阅读文档,而不是试图破解它。