使用 jdbc 模板自动装配数据源问题的 Spring Boot 自动配置
Posted
技术标签:
【中文标题】使用 jdbc 模板自动装配数据源问题的 Spring Boot 自动配置【英文标题】:spring boot autoconfiguration with jdbc template autowiring dataSource issue 【发布时间】:2015-02-26 03:07:57 【问题描述】:我是 Spring 和 J2EE 的新手。我在使用带有 Spring Boot 自动配置的 JDBC 模板时遇到问题。
我所做的是以here提供的RESTful Web服务为例 并决定将其扩展为使用 JDBC 模板关系数据库访问。不幸的是,提供的另一个 example 没有用,因为没有考虑从 xml beans 文件提供数据源的唯一困难。
我试图解决的问题:
-
使用 DAO Impl 类作为 Spring 不同实现的扩展。
添加到 beans 文件。
使用不同的 DataSource 类(例如 DriverManagerDataSource)。
尝试仅自动装配不同类中的简单属性(比数据源更简单)。
一开始我刚刚编写了 DAO 类,但后来我认为只有实现接口才能自动连接数据源,尝试过,但没有帮助。
我尝试了在 Stack 或 Google 上找到的所有内容。大多数示例都严重过时或没有答案,或者与 Spring Boot 自动配置等无关。
我一直收到Property 'dataSource' is required
错误,经过努力,如果最终设法将application-config.xml
文件与bean 链接起来,但无法为JDBC 自动装配数据源。
我迫不及待地完成它并严重阻止,出于想法,如果有人可以提供一个最近的示例,它适用于 Spring Boot 自动配置、XML 中的 bean 查找、JDBC 的自动装配数据源。
或者至少是一些想法,线索,甚至是如何寻找它,因为我什至没有关键词可供谷歌搜索。
谢谢!
Spring 应用程序类。
package ws;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
@Configuration
@ComponentScan
@ImportResource("classpath:spring/application-config.xml")
@EnableAutoConfiguration
public class Application
public static void main(String[] args)
SpringApplication.run(Application.class, args);
Web 服务类。
package ws;
import dao.UserDAOImpl;
import model.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestWS
@RequestMapping("/greeting")
public User greeting(@RequestParam(value="name", defaultValue="World") String name)
return new User("ubububu", "661331555", 0);
@RequestMapping("/create")
public String initialize()
UserDAOImpl users = new UserDAOImpl();
users.init();
return "seems ok";
DAO 接口
package dao;
import model.User;
public interface UserDAO
public void insert(User usr);
public void init();
public User select(int id);
DAO 实现
package dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.stereotype.Repository;
import model.User;
import dao.UserDAO;
@Repository
public class UserDAOImpl implements UserDAO
private JdbcTemplate jdbcTemplate;
private DriverManagerDataSource dataSource;
@Autowired
public void setDataSource(DriverManagerDataSource dataSource)
this.dataSource = dataSource;
public void insert(User usr)
String sql = "INSERT INTO USER " +
"(USR_ID, EMAIL, PHONE) VALUES (?, ?, ?)";
this.jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.execute(sql);
public void init()
String sql = "CREATE TABLE USER (USR_ID INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,EMAIL VARCHAR(30) NOT NULL,PHONE VARCHAR(15) NOT NULL)";
this.jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.execute(sql);
数据模型
package model;
public class User
private String email;
private String phone;
private int id;
public User(String email, String phone, int id)
this.email = email;
this.phone = phone;
this.id = id;
public int getUsrId()
return this.id;
public String getUsrEmail()
return this.email;
public String getUsrPhone()
return this.phone;
配置bean文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 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/context http://www.springframework.org/schema/context/spring-context.xsd">
<import resource="Spring-User.xml" />-->
<context:component-scan base-package="ws"/>
<bean id="ds"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.springframework.jdbc.core.JdbcTemplate" />
<property name="url" value="jdbc:mysql://localhost/:3306/databasename" />
<property name="username" value="root" />
<property name="password" value="password" />
</bean>
<bean id="UserDAOprovider" class="dao.UserDAOImpl">
<property name="dataSource" ref="ds" />
</bean>
</beans>
错误信息:
ERROR [dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalArgumentException: Property 'dataSource' is required] with root cause
java.lang.IllegalArgumentException: Property 'dataSource' is required
at org.springframework.jdbc.support.JdbcAccessor.afterPropertiesSet(JdbcAccessor.java:135) ~[spring-jdbc-4.0.8.RELEASE.jar!/:4.0.8.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.<init>(JdbcTemplate.java:169) ~[spring-jdbc-4.0.8.RELEASE.jar!/:4.0.8.RELEASE]
at dao.UserDAOImpl.init(UserDAOImpl.java:66) ~[demo3-0.0.1-SNAPSHOT.jar!/:na]
at ws.TestWS.initialize(TestWS.java:30) ~[demo3-0.0.1-SNAPSHOT.jar!/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.6.0_33]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.6.0_33]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.6.0_33]
at java.lang.reflect.Method.invoke(Method.java:622) ~[na:1.6.0_33]
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215) ~[spring-web-4.0.8.RELEASE.jar!/:4.0.8.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132) ~[spring-web-4.0.8.RELEASE.jar!/:4.0.8.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) ~[spring-webmvc-4.0.8.RELEASE.jar!/:4.0.8.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749) ~[spring-webmvc-4.0.8.RELEASE.jar!/:4.0.8.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689) ~[spring-webmvc-4.0.8.RELEASE.jar!/:4.0.8.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83) ~[spring-webmvc-4.0.8.RELEASE.jar!/:4.0.8.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938) ~[spring-webmvc-4.0.8.RELEASE.jar!/:4.0.8.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870) ~[spring-webmvc-4.0.8.RELEASE.jar!/:4.0.8.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961) ~[spring-webmvc-4.0.8.RELEASE.jar!/:4.0.8.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852) ~[spring-webmvc-4.0.8.RELEASE.jar!/:4.0.8.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:620) ~[tomcat-embed-core-7.0.57.jar!/:7.0.57]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837) ~[spring-webmvc-4.0.8.RELEASE.jar!/:4.0.8.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) ~[tomcat-embed-core-7.0.57.jar!/:7.0.57]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) ~[tomcat-embed-core-7.0.57.jar!/:7.0.57]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) ~[tomcat-embed-core-7.0.57.jar!/:7.0.57]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) ~[spring-web-4.0.8.RELEASE.jar!/:4.0.8.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.0.8.RELEASE.jar!/:4.0.8.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) ~[tomcat-embed-core-7.0.57.jar!/:7.0.57]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) ~[tomcat-embed-core-7.0.57.jar!/:7.0.57]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) ~[tomcat-embed-core-7.0.57.jar!/:7.0.57]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) ~[tomcat-embed-core-7.0.57.jar!/:7.0.57]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503) ~[tomcat-embed-core-7.0.57.jar!/:7.0.57]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) ~[tomcat-embed-core-7.0.57.jar!/:7.0.57]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) ~[tomcat-embed-core-7.0.57.jar!/:7.0.57]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) ~[tomcat-embed-core-7.0.57.jar!/:7.0.57]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421) ~[tomcat-embed-core-7.0.57.jar!/:7.0.57]
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070) ~[tomcat-embed-core-7.0.57.jar!/:7.0.57]
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611) ~[tomcat-embed-core-7.0.57.jar!/:7.0.57]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1736) ~[tomcat-embed-core-7.0.57.jar!/:7.0.57]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1695) ~[tomcat-embed-core-7.0.57.jar!/:7.0.57]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146) ~[na:1.6.0_33]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) ~[na:1.6.0_33]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-7.0.57.jar!/:7.0.57]
at java.lang.Thread.run(Thread.java:701) ~[na:1.6.0_33]
【问题讨论】:
【参考方案1】:在 Spring Boot 中配置 DataSource 最简单的方法是在 src/main/resources 下创建一个 application.properties 文件,内容如下(可能需要使用正确的 url、用户名和密码进行更新):
spring.datasource.url=jdbc:mysql://localhost/:3306/databasename
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
Spring Boot 会自动为您创建 DataSource 类并将其注入其他 bean。因此,您将不再需要 xml 配置文件,并且可以在 Application 类中去掉这一行:
@ImportResource("classpath:spring/application-config.xml")
此外,在 UserDAOImpl 中,Spring 可以使用 DataSource bean (http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-sql.html#boot-features-using-jdbc-template) 自动装配 JdbcTemplate 对象,因此您无需在每次调用 insert() 方法时都创建一个。
至于UserDAOImpl中的init()方法,你可以在src/main/resources下创建一个schema.sql文件,并将CREATE TABLE语句移到那里(更多细节见http://docs.spring.io/spring-boot/docs/1.2.0.RELEASE/reference/htmlsingle/#howto-intialize-a-database-using-spring-jdbc)
有关更多信息,请参阅此示例:http://xantorohara.blogspot.ca/2013/11/spring-boot-jdbc-sample.html
【讨论】:
感谢 kaviddiss 的回答。我刚刚在 src/main/resources 下创建了 application.properties 文件,不幸的是我一直收到相同的错误消息。我还尝试将它放在 src/main/resources/spring 目录下,结果相同。确定一定是com.mysql.jdbc.Driver作为驱动包吗? 您收到的错误信息是什么?驱动程序类名称特定于您正在使用的数据库。如果是mysql,属性文件中的值应该是com.mysql.jdbc.Driver。 是mysql,这种情况下驱动是正确的。堆栈消息太长,无法在评论中发布,所以我编辑了问题,在最后添加了它。再次感谢! 可以试试在UserDAOImpl的setDataSource()方法中将DriverManagerDataSource改为DataSource吗? 请查看以下链接以获取帮助:xantorohara.blogspot.ca/2013/11/spring-boot-jdbc-sample.html 和 blog.netgloo.com/2014/10/27/…以上是关于使用 jdbc 模板自动装配数据源问题的 Spring Boot 自动配置的主要内容,如果未能解决你的问题,请参考以下文章