Можно ли использовать JDB C Template и JDB C MySQL одновременно? - PullRequest
1 голос
/ 25 апреля 2020

В настоящее время я создаю простое приложение на основе CRUD, и я закончил с основами c, такими как создание формы с заголовком, датой, описанием и т. Д. c, редактирование или удаление сообщения и т. П. c. Так что теперь я пытаюсь добавить функцию загрузки изображений. (Я использую Windows 10 в качестве моей ОС)

В данный момент я изучаю учебное пособие по следующему URL

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

Я предполагаю, что причина конфликта заключается в том, что я пытаюсь использовать базу данных JDB C H2 и JDB C MySQL одновременно. Сначала я думал, что комментирование моей исходной конфигурации, как показано ниже, решит проблему,

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

, но после этого я не смог запустить программу, вероятно, потому что есть часть, где я использую JDB C 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); 
……

Мой самый большой вопрос: как я могу интегрировать функцию учебника «Загрузить изображение» в мое базовое c приложение CRUD, не вызывая конфликта в конфигурация?

Должен ли я отказаться от использования базы данных JDB C H2 и шаблона JDB C и использовать что-то еще, совместимое с частью JDB C MySQL, которую я извлекаю из руководства? Другими словами, для того, чтобы интегрировать функцию загрузки изображений из учебного пособия, должен ли я кардинально реструктурировать свой код в файл ReportDaoImpl.java (и, возможно, даже в другие файлы?), Или будет простой способ разрешения конфликта конфигурации?

Ответы [ 2 ]

2 голосов
/ 26 апреля 2020

Вам не нужно отдавать ни одну из ваших баз данных, если вы собираетесь использовать их по абсолютно необходимым причинам. 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
Добавить 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());
    }
}

Используйте в правом 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 для всех соответствующих классов репозитория.

Приветствия и счастливые кодирования!

2 голосов
/ 25 апреля 2020

Вы не можете определить один и тот же ключ несколько раз в application.properties, один переопределит другой. Это означает, что если вам нужно использовать несколько источников данных (для MySQL и H2), вы не можете полагаться на spring.datasource.xxx в application.properties. Вместо этого определите два источника данных явно самостоятельно. См. Официальный документы для примера.

Кроме того, JdbcTemplate будет настроен, только если:

  • Только один DataSource определен
  • Если определено несколько DataSource, но только один DataSource помечен как @Primary, и он будет настроен только для этого @Primary источника данных.

Таким образом, это означает, что после определения нескольких источников данных вы должны пометить H2 как @Primary что JdbcTemplate будет автоматически сконфигурирован для него только для того, чтобы гарантировать, что ваши существующие коды JDBCTempalte по-прежнему взаимодействуют с H2, но не MySQL.

Кстати, нет преимуществ в использовании нескольких баз данных для простого приложения CRUD. Вы столкнетесь с проблемами, если захотите провести транзакцию, охватывающую данные из нескольких баз данных. Я предлагаю вам выбрать только один для такого простого приложения.

(см. Также мой связанный ответ для более подробной информации)

...