【问题标题】:Is it possible to use JDBC Template and JDBC MySQL at the same time?可以同时使用 JDBC Template 和 JDBC MySQL 吗?
【发布时间】:2020-08-09 08:51:19
【问题描述】:

我目前正在构建一个简单的基于 CRUD 的应用程序,并且我已经完成了基本的工作,例如创建带有标题、日期、描述等的表单,编辑或删除帖子等。所以现在我正在尝试添加图片上传功能。 (我使用 Windows 10 作为我的操作系统)

目前正在学习以下网址的教程

https://www.callicoder.com/spring-boot-file-upload-download-jpa-hibernate-mysql-database-example/

,当我看的时候

配置数据库和多部分文件属性

部分,它解释了配置数据库和多部分文件属性需要哪些语句,但是当我添加教程页面的示例时,它导致了冲突。

下面是我的application.properties 文件的样子。

“## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties”后面是我从教程中复制粘贴的部分,上面是添加教程之前的原始代码)

spring.datasource.url=jdbc:h2:mem:test
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.h2.console.enabled=true

## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url= jdbc:mysql://localhost:3306/file_demo?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
spring.datasource.username= root
spring.datasource.password= callicoder

## Hibernate Properties

# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto = update

## Hibernate Logging
logging.level.org.hibernate.SQL= DEBUG

## MULTIPART (MultipartProperties)
# Enable multipart uploads
spring.servlet.multipart.enabled=true
# Threshold after which files are written to disk.
spring.servlet.multipart.file-size-threshold=2KB
# Max file size.
spring.servlet.multipart.max-file-size=200MB
# Max Request Size
spring.servlet.multipart.max-request-size=215MB

导致冲突的部分如下。

spring.datasource.url=jdbc:h2:mem:test
spring.datasource.username=sa

spring.datasource.url= jdbc:mysql://localhost:3306/file_demo?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
spring.datasource.username= root

我认为冲突的原因是我试图同时使用 JDBC H2 数据库和 JDBC MySQL。起初我认为像下面这样注释掉我的原始配置可以解决问题,

#spring.datasource.url=jdbc:h2:mem:test
#spring.datasource.driverClassName=org.h2.Driver
#spring.datasource.username=sa
#spring.h2.console.enabled=true

,但是在这之后我无法运行程序,可能是因为有一部分我使用了 JDBC Templace,如下所示。

[ReportDaoImpl.java]

package com.example.demo.repository;

import java.sql.Timestamp;

@Repository
public class ReportDaoImpl implements ReportDao {
    
    private final JdbcTemplate jdbcTemplate; 
    
    @Autowired
    public ReportDaoImpl(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate; 
    }

    @Override
    public List<Report> findAll() {
        String sql = "SELECT report_id, title, threat_level, report_date, description, img_path, "
                            + "user.user_id, user_name FROM report "
                            + "INNER JOIN user ON report.user_id = user.user_id";
        
        List<Map<String, Object>> resultList = jdbcTemplate.queryForList(sql); 
……

我最大的问题是,如何将教程的“上传图像”功能集成到我的基本 CRUD 应用程序中而不会导致配置冲突?

我是否应该放弃使用 JDBC H2 数据库和 JDBC 模板并使用与我从教程中获取的 JDBC MySQL 部分兼容的其他东西?换句话说,为了集成教程的图片上传功能,我应该从根本上重构我的代码在ReportDaoImpl.java文件中(甚至可能还有其他文件?),还是有一个简单的方法来解决配置冲突?

【问题讨论】:

    标签: mysql spring-boot h2


    【解决方案1】:

    您不能在 application.properties 中多次定义同一个键,一个会覆盖另一个。这意味着如果您需要使用多个数据源(对于 MySQL 和 H2),您不能依赖 application.properties 中的 spring.datasource.xxx。相反,请自行明确定义这两个 DataSource。示例见官方docs

    另外,JdbcTemplate 将仅在以下情况下配置:

    • 只定义了一个DataSource
    • 如果定义了多个DataSource,但只有一个DataSource被标记为@Primary,它将只为这个@Primary数据源配置。

    这意味着在您定义多个 DataSource 之后,您必须将 H2 标记为 @Primary 以便自动为其配置 JdbcTemplate 以确保您现有的 JDBCTempalte 相关代码仍然与 H2 交互但不是 MySQL。

    顺便说一句,对一个简单的 CRUD 应用程序使用多个数据库没有任何好处。如果您想要一个涵盖来自多个数据库的数据的事务,您将遇到问题。我建议你只为这样一个简单的应用选择一个。

    (有关更多详细信息,请参阅我的相关@​​987654322@)

    【讨论】:

    • 感谢您的建议!是的,你指出的有道理。管理两个不同的数据库比管理一个数据库更困难。我也感谢您分享的链接:)
    【解决方案2】:

    如果您出于绝对必要的原因打算使用它们,则不必放弃任何数据库。 Spring 没有 DataSourceAutoConfiguration 无法区分属性文件中的两个配置,因为属性文件是一个键值对映射。因此它会覆盖配置。

    解决此问题的最简单方法是:

    1. 为不同的数据源创建单独的键,如下所示:
    ## Your Primary Data Source
    spring.datasource-primary.url=jdbc:h2:mem:test
    spring.datasource-primary.driverClassName=org.h2.Driver
    spring.datasource-primary.username=sa
    spring.h2.console.enabled=true
    
    ## Your Secondary Data Source
    spring.datasource-secondary.url= jdbc:mysql://localhost:3306/file_demo?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
    spring.datasource-secondary.username= root
    spring.datasource-secondary.password= callicoder
    
    1. 添加一个 DataSourceConfig 如下
    package com.example.demo.config;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.core.env.Environment;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.jdbc.datasource.DriverManagerDataSource;
    
    import javax.sql.DataSource;
    
    /**
     * Configures the Spring-managed resources for Common Services/Utils.
     */
    @Configuration
    public class DataSourceConfig {
    
        @Autowired
        Environment env;
    
        /**
         * Primary DataSource (Meaning the one that is your parent transaction manager)
         */
        @Bean
        @Primary
        public DataSource h2DataSource() {
            DriverManagerDataSource dataSource = new DriverManagerDataSource();
            dataSource.setDriverClassName(env.getProperty("spring.datasource-primary.driverClassName"));
            dataSource.setUrl(env.getProperty("spring.datasource-primary.url"));
            dataSource.setUsername(env.getProperty("spring.datasource-primary.username"));
            dataSource.setPassword(env.getProperty("spring.datasource-primary.password"));
            return dataSource;
        }
    
        /**
         * @usage Autowire this in your JPA Repositories using
         *      @Autowired
         *      JdbcTemplate h2JdbcTemplate;
         */
        @Bean
        public JdbcTemplate h2JdbcTemplate() {
            return new JdbcTemplate(h2DataSource());
        }
    
        /**
         * Secondary DataSource (Meaning the one that can cause the parent transaction to roll-back on exception)
         */
        @Bean
        public DataSource mysqlDataSource() {
            DriverManagerDataSource dataSource = new DriverManagerDataSource();
            dataSource.setDriverClassName(env.getProperty("spring.datasource-secondary.driverClassName"));
            dataSource.setUrl(env.getProperty("spring.datasource-secondary.url"));
            dataSource.setUsername(env.getProperty("spring.datasource-primary.username"));
            dataSource.setPassword(env.getProperty("spring.datasource-secondary.password"));
            return dataSource;
        }
    
        /**
         * @usage Autowire this in your JPA Repositories using
         *      @Autowired
         *      JdbcTemplate mysqlJdbcTemplate;
         */
        @Bean
        public JdbcTemplate mysqlJdbcTemplate() {
            return new JdbcTemplate(mysqlDataSource());
        }
    }
    
    
    1. 在您的存储库类中使用正确的 JdbcTemplate
    package com.example.demo.repository;
    
    import java.sql.Timestamp;
    
    @Repository
    public class ReportDaoImpl implements ReportDao {
    
        //Note the JdbcTemplate variable name here
        private final JdbcTemplate myslJdbcTemplate; 
    
        @Autowired
        //Note the JdbcTemplate variable name here
        public ReportDaoImpl(JdbcTemplate myslJdbcTemplate) {
            this.jdbcTemplate = jdbcTemplate; 
        }
    
        @Override
        public List<Report> findAll() {
            String sql = "SELECT report_id, title, threat_level, report_date, description, img_path, "
                                + "user.user_id, user_name FROM report "
                                + "INNER JOIN user ON report.user_id = user.user_id";
    
            List<Map<String, Object>> resultList = jdbcTemplate.queryForList(sql); 
    ……
    

    您需要为所有相应的存储库类更新相应的 JdbcTemplate。

    干杯,编码愉快!

    【讨论】:

    • 感谢您提供非常详细的建议!您包含代码 sn-ps 作为具体示例也是额外的帮助:D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-26
    • 2017-03-01
    • 1970-01-01
    • 2010-12-26
    • 1970-01-01
    • 2011-12-02
    相关资源
    最近更新 更多