是否可以同时使用JDBC模板和JDBCMySQL?
Is it possible to use JDBC Template and JDBC MySQL at the same time?
我目前正在构建一个简单的基于 CRUD 的应用程序,我已经完成了基本的工作,比如创建一个带有标题、日期、描述等的表单,编辑或删除 post 等。所以现在我也在尝试添加图片上传功能。 (我使用 Windows 10 作为我的 OS)
目前正在学习以下教程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
我假设冲突的原因是我试图同时使用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
文件(甚至可能是其他文件?)中的代码,或者是否有一种简单的方法来解决配置冲突?
您不能在 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 应用程序,使用多个数据库没有任何优势。如果您想要一个涵盖来自多个数据库的数据的事务,您将遇到问题。这么简单的app我建议你只选一个。
(另请参阅我的相关 了解更多详情)
如果您出于绝对必要的原因打算使用它们,则不必放弃任何数据库。 Spring DataSourceAutoConfiguration 不能区分 属性 文件中的两个配置,因为 属性 文件是一个键值对映射。因此它会覆盖配置。
解决此问题的最简单方法是:
- 为不同的数据源创建单独的密钥,如下所示:
## 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 类。
干杯,编码愉快!
我目前正在构建一个简单的基于 CRUD 的应用程序,我已经完成了基本的工作,比如创建一个带有标题、日期、描述等的表单,编辑或删除 post 等。所以现在我也在尝试添加图片上传功能。 (我使用 Windows 10 作为我的 OS)
目前正在学习以下教程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
我假设冲突的原因是我试图同时使用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
文件(甚至可能是其他文件?)中的代码,或者是否有一种简单的方法来解决配置冲突?
您不能在 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 应用程序,使用多个数据库没有任何优势。如果您想要一个涵盖来自多个数据库的数据的事务,您将遇到问题。这么简单的app我建议你只选一个。
(另请参阅我的相关
如果您出于绝对必要的原因打算使用它们,则不必放弃任何数据库。 Spring DataSourceAutoConfiguration 不能区分 属性 文件中的两个配置,因为 属性 文件是一个键值对映射。因此它会覆盖配置。
解决此问题的最简单方法是:
- 为不同的数据源创建单独的密钥,如下所示:
## 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 类。
干杯,编码愉快!