質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

JDBC

JDBC(Java DataBase Connectivity)は、Javaとリーレーショナルデータベースに接続させる基本的なAPIです。Java上でSQLステートメントを発行することで、データベースの種類に影響を受ないDB操作を可能とします。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

Q&A

解決済

1回答

894閲覧

Configurationでコンフリクトを起こさずにJDBC TemplateとJDBC MySQLを使うには?

Sean2014

総合スコア59

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

JDBC

JDBC(Java DataBase Connectivity)は、Javaとリーレーショナルデータベースに接続させる基本的なAPIです。Java上でSQLステートメントを発行することで、データベースの種類に影響を受ないDB操作を可能とします。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

1グッド

0クリップ

投稿2020/04/25 19:27

編集2020/04/25 19:29

Java Spring Bootで基本的なCRUD機能の練習用アプリに画像アップロード機能も実装したくて下記URLのチュートリアルを読んでいるのですが、つまづいている所があります。

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

このチュートリアルの

#Configuring the Database and Multipart File properties

という項目でDatabaseとMultipart file propertiesをConfigureする必要があると書かれており、チュートリアルの記述を自分のapplication.propertiesファイルに追加したらコンフリクトが生じてしまいました。

下記がその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

Configurationでコンフリクトを起こしているのは下記の4行分です。

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 databaseとJDBC MySQLを同時に使おうとしているからでしょうか。最初は下記のように自分の元のConfigurationの記述をコメントアウトして、チュートリアルのもので完全に上書きすれば問題解決すると思っていたのですが、

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

この状態でプログラムを実行しようしてもできませんでした。たぶんH2のConfiguration部分をコメントアウトしたのに下記コードのようにJDBC Templateを使おうとしている箇所が存在するからだと思います。

#[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); ……

ここで気になるのは、どうやったらConfigurationのコンフリクトを起こさずに冒頭URLのチュートリアルの画像アップロードの機能を組み込めるのか?という事です。

このチュートリアルの画像アップロード機能を組み込もうとしている時点で、そもそもJDBC H2 Databaseを使おうとしているのが間違いで、JDBC Templateの代わりに何か他の方法でDatabaseのデータにアクセスするというやり方になるように、根本的にReportDaoImpl.javaのファイルを書き換えないといけないのでしょうか?それとも、もっと単純にConfigurationコンフリクトを解消する方法はあるのでしょうか?

sonotasan2017👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2020/04/25 20:44

h2DBを使いたいのでしょうか。 MySQLを使いたいのでしょうか。 それとも両方使う要件なのでしょうか。
退会済みユーザー

退会済みユーザー

2020/04/26 00:34

spring jdbc 服薄データソース とかで検索したらそこそこ情報でてくるが 調べないで質問でしょうか?
Sean2014

2020/04/26 07:09

H2DBとMySQLを両方使おうとしています。
Sean2014

2020/04/26 11:14

Stack Overflowでも同じ内容の質問をしていたのですが、こちらでは文脈が十分に書かれ、わかりやすい具体例も示してある非常に良質な回答が得られました。質問者だけでなく、回答者の目線で見ても参考になる部分の多い回答ですのでぜひご覧ください。このコメント欄にはStack Overflowでの元の投稿のリンク(英語)を追記しておきますが、先ほど日本語訳したものもこの質問に対する回答として投稿しておきました。 https://stackoverflow.com/questions/61431112/is-it-possible-to-use-jdbc-template-and-jdbc-mysql-at-the-same-time/61432715#61432715
退会済みユーザー

退会済みユーザー

2020/04/26 12:12

Stack Overflow ⇒ なんでもいいから 情報を貯めよう Teratail ⇒ 少しは自分で調べて実行それでもわからなかったら質問しよう、またマルチポストは非推奨 という利用規約の違いからかと
Sean2014

2020/04/26 13:08 編集

「少しは自分で調べて実行それでもわからなかったら質問しよう」 →これはStack Overflowも同じです。 「なんでもいいから情報を貯めよう」 →情報のソースが不明です。
guest

回答1

0

自己解決

Stack Overflowでも同じ質問をしていたのですが、こちらでは非常に親切で丁寧なご回答をいただけたので日本語に訳して共有します。
(元の投稿のURL)
https://stackoverflow.com/questions/61431112/is-it-possible-to-use-jdbc-template-and-jdbc-mysql-at-the-same-time/61432715#61432715

#【1人目の回答者】
それが必要な状況であるならば、データベースの片方(H2)の使用を諦める必要はありません。Spring DataSourceAutoConfigurationはプロパティファイルに2つの異なるConfigがあると区別がつけられません。プロパティファイルはキーと値のペアの構造になっているからです。従って、片方がもう片方をオーバーライドしてしまいます。

簡単な解決策としては、以下のようなものが考えられます。

(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

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

(3)RepositoryクラスでJdbcTemplateをMySQLに適合する形に修正する事

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人目の回答者】
application.properties内では同じキーを複数回違う値で設定する事はできません。片方がもう片方をオーバーライドしてしまいます。これはつまり、データソースを複数使う場合は単にspring.datasource.〇〇〇という形の記述をするだけではダメだという事です。代わりに、2つのデータソースを自分で明確に定義するようにしてください。こちらにオフィシャルなドキュメンテーションもあります。
https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-two-datasources

それから、JdbcTemplateをConfigureできるのは次のような場合のみです。

・データソースが1つしか定義されていない
・複数のデータソースが定義されていても、そのうち1つに@Primaryとアノテーションを付けておけば、それがメインのデータソースとして設定される

つまり、あなたのケースでは、H2を@PrimaryとすればJdbcTemplateの部分も自動的に設定がされ、今使ってるJDBCTemplateのコードもMySQLではなくH2とやりとりをする事になります。

ちなみに、簡単なCRUDアプリ程度であればデータベースを複数使う利点は特にありません。複数のデータベースにまたがるデータをカバーしたい時に面倒な事になるでしょう。シンプルなアプリであれば、データベースは1つにするのをオススメします。

(以下の記事も参考になるので、より詳しい情報が必要であればこちらも読んでみてください)
https://stackoverflow.com/questions/61170848/exclude-certain-datasources-from-hibernatejpaautoconfiguration/61172378#61172378

投稿2020/04/26 11:09

編集2020/04/26 11:16
Sean2014

総合スコア59

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問