使用 jdbc 模板自动装配数据源问题的 Spring Boot 自动配置

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27697190/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 00:16:33  来源:igfitidea点击:

spring boot autoconfiguration with jdbc template autowiring dataSource issue

springjdbcdatasourcespring-bootautowired

提问by Marek

I'm new to Spring and to J2EE in general. I'm having trouble using JDBC template with Spring Boot autoconfiguration.

我是 Spring 和 J2EE 的新手。我在使用带有 Spring Boot 自动配置的 JDBC 模板时遇到问题。

What I did was I took the example of RESTful web service provided hereand decided to extend it to use JDBC template relational database access. Unfortunately another exampleprovided cannot be useful because the only difficulty which is providing dataSource from xml beans file is not considered.

我所做的是以此处提供的 RESTful Web 服务为例, 并决定将其扩展为使用 JDBC 模板关系数据库访问。不幸的是,提供的另一个示例没有用,因为没有考虑从 xml beans 文件提供数据源的唯一困难。

What I tried to solve the issue:

我试图解决的问题:

  1. Using DAO Impl class as extend of different implementations from Spring.
  2. Adding to beans file.
  3. Using different DataSource classes (eg DriverManagerDataSource).
  4. Trying to autowire just a simple attribute in a different class (something less complex then data source).
  5. On the beggining I just written DAO class, but then I though that maybe it is possible to autowire datasource only if it implements an interface, tryed it, didn't help.
  1. 使用 DAO Impl 类作为 Spring 不同实现的扩展。
  2. 添加到beans文件。
  3. 使用不同的 DataSource 类(例如 DriverManagerDataSource)。
  4. 试图在不同的类中自动装配一个简单的属性(比数据源更简单的东西)。
  5. 一开始我只是写了 DAO 类,但后来我认为也许只有当它实现一个接口时才有可能自动装配数据源,尝试过它,没有帮助。

I tryed everything I found on Stack or Google. Most examples are seriously outdated or unanswered or have nothing to do with Spring Boot Autoconfiguration et cetera.

我尝试了我在 Stack 或 Google 上找到的所有内容。大多数示例都严重过时或没有答案,或者与 Spring Boot Autoconfiguration 等无关。

I keep getting Property 'dataSource' is requirederror, after struggling if finally managed to link the application-config.xmlfile with beans, but can't manage to autowire the datasource for JDBC.

Property 'dataSource' is required如果最终设法将application-config.xml文件与 bean链接起来,我不断收到错误消息,但无法设法为 JDBC 自动装配数据源。

I'm desperade to finish it and seriously blocked, out of ideas, I would be greatfull if somebody could provide a recent example that works with Spring Boot Autoconfigurations, beans in XML find, autowired datasource for JDBC.

我迫不及待地完成它并严重受阻,出于想法,如果有人能提供一个最近的示例,该示例可与 Spring Boot 自动配置、XML 中的 bean 查找、JDBC 的自动装配数据源一起使用,我会非常高兴。

Or at least some ideas, clues, even how to look for it, because I'm even out of keywords for google'ing.

或者至少有一些想法、线索,甚至是如何寻找它,因为我什至没有 google'ing 的关键字。

Thanks!

谢谢!

enter image description here

在此处输入图片说明

Spring Application class.

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 Service class.

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 interface

DAO接口

package dao;

import model.User;

public interface UserDAO {
    public void insert(User usr);
    public void init();
    public User select(int id);
}

DAO implementation

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);
    }
}

Data model

数据模型

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;
    }
}

Configuration bean file

配置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 message:

错误信息:

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]

回答by kaviddiss

The simplest way to configure a DataSource in Spring Boot is to create an application.properties file under src/main/resources with the following content (may need to update it with correct url, username and password):

在 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 will automatically create the DataSource class for you and inject it to other beans. As a result of that, you won't need the xml config file anymore and may get rid of this line in the Application class:

Spring Boot 会自动为你创建 DataSource 类并将其注入到其他 bean 中。因此,您将不再需要 xml 配置文件,并且可以删除 Application 类中的这一行:

@ImportResource("classpath:spring/application-config.xml")

Also, in the UserDAOImpl Spring can autowire the JdbcTemplate object using the DataSource bean (http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-sql.html#boot-features-using-jdbc-template) so you don't need to create one each time the insert() method is called.

此外,在 UserDAOImpl Spring 可以使用 DataSource bean 自动装配 JdbcTemplate 对象(http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-sql.html#boot-features- using-jdbc-template) 这样你就不需要在每次调用 insert() 方法时都创建一个。

As for the init() method in UserDAOImpl, you could create a schema.sql file under src/main/resources and move the CREATE TABLE statement there (for more details see http://docs.spring.io/spring-boot/docs/1.2.0.RELEASE/reference/htmlsingle/#howto-intialize-a-database-using-spring-jdbc)

至于 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

See this example for more information: http://xantorohara.blogspot.ca/2013/11/spring-boot-jdbc-sample.html

有关更多信息,请参阅此示例:http: //xantorohara.blogspot.ca/2013/11/spring-boot-jdbc-sample.html