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

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

ただいまの
回答率

87.61%

Mysql環境をdockerで作成しアプリケーションと連携したい(spring boot)

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,389

score 87

□環境情報□
macOS:10.14.2
spring boot:2.1
Docker:version 18.09.1
mysql:8.0

やりたいこと

dockerにて構築したmysql環境から値を取得し画面に表示する
※docker環境の中のmysqlの今回の対象のテーブル情報を以下に載せます
イメージ説明

現状

findAll()メソッドにて値が取得できない

ソース情報

データベース名:demo
テーブル名:Account
カラム:id,email,password

以下デバッグ画像のfindAll()にてカラムid,email,passwordが取りたいのに、、、sizeが0で返ってくる。
イメージ説明

その他ソース

githubリンク
※findAll()はこちら側で別個定義が必要なのでしょうか?
それともDBと連携ができていない?
ご意見を宜しくお願いいたします。

spring.datasource.url=jdbc:mysql://localhost:3306/demo?useSSL=false
spring.datasource.username=root
spring.datasource.password=p@ssw0rd
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.database=MYSQL
spring.jpa.hibernate.ddl-auto=update
package com.example.demo;

import lombok.Data;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "Account")
@Data
public class AccountEntiry {

    @Column
    @Id
    private int id;

    @Column
    private String email;

    @Column
    private String password;

}
package com.example.demo;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface AccountRepository extends JpaRepository<AccountEntity,Integer> {
}
package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class AccountService {
    @Autowired
    AccountRepository accountRepository;


}
package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

@Controller
@RequestMapping("/")
public class IndexController {
    @Autowired
    AccountRepository accountRepository;

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String index(Model model) {
        List<AccountEntiry> emplist=accountRepository.findAll();
        model.addAttribute("emplist", emplist);

        model.addAttribute("message", "Hello Springboot");
        return "index";

    }
}

■修正情報■

■1/31■成果振り返り

まず、JpaRepository<Account,String>としていたものをidの属性であるJpaRepository<Account,Integer>へ変更。

デバッグ実行後、事象変わらず、、、SimpleJpaRepositoryを掘っていたら以下のエラーが出ていることが判明。

Method threw 'java.lang.IllegalStateException' exception. Cannot evaluate com.sun.proxy.$Proxy84.toString()


イメージ説明
今日はここまで。眠って、明日の業務後にデバッグします!

■2/1■成果振り返り

空いていたWindowsPCでローカル環境に直接MySql環境を構築し同じプロジェクトをgithubより落としてきて実行した。
→データベース連携成功...
dockerと何が違うのか...
以下Windowsでのデバッグ時画面とMacでの同じ場所での画像比較
■Windows
Windows画面
■Mac
イメージ説明

Macでは以下のエラーが出ている。

((SimpleJpaRepository)((SingletonTargetSource)((ProxyFactory)((JdkDynamicAopProxy)this.h).advised).t = No such instance field: 'h'

■2/2■成果振り返り

前回まででMysqlをローカルで環境構築してアプリケーションの動作がどうなるかを検証しました。
Windowsにて検証を行ったのですが同じソース、同じデータベース構造でデータベースの内容を画面へ表示することができました。
dockerとローカルで何が違うのか...

~~### 現在詰まっている箇所
イメージ説明
ローカルで実行した際には出ないエラーの調査をしています。

((SimpleJpaRepository)((SingletonTargetSource)((ProxyFactory)((JdkDynamicAopProxy)this.h).advised).t = No such instance field: 'h'

hフィールドを探す

hどこやねん

/Library/Java/JavaVirtualMachines/jdk-11.0.2.jdk/Contents/Home/lib/src.zip!/java.base/java/lang/reflect/Proxy.java


上記パス中にいました。
Proxy.javaてなんだ?
イメージ説明

hフィールドのエラー関係ない!!!!!!!

・macのローカル環境あんまり汚したくなかったけど仕方なくローカルにMysql環境構築しデータベース連携できるか確認
→連携成功。。。やはりdockerの設定に問題がある模様。
そして散々調べていたhフィールドですが、これはmac環境固有のもの?らしく、こちらが発生していてもデータベースとの連携は下図のように成功していました。。。

2月2日現状...どのように切り分けするべきかわからなくなっております。。。。ご意見をください。よろしくお願いいたします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • asahina1979

    2019/01/30 08:47

    データが登録されてないだけ

    キャンセル

  • sanezane

    2019/01/30 12:13

    asahima1979さん
    ありがとうございます。しかし、最上部の画像(画像下部)にある通り1レコードだけですが、登録は確認しています。

    キャンセル

  • asahina1979

    2019/01/30 12:35 編集

    見てる場所が違うきがしないでもないが

    キャンセル

  • sanezane

    2019/01/30 14:02

    リポジトリが生成されているので接続自体は成功してると認識してますが、、そこからのアプローチをどうしようか考えております。
    帰ったらまたデバッグしてみます!

    キャンセル

回答 1

checkベストアンサー

+1

下記のファイルを修正することで正常に動作させることができると思います。
また、回答に記載したコードは質問文に書かれていたGitHubのリポジトリから転用させて頂きました。

V1_Account_create.sql

おそらく、今回の問題の一番の原因がこのsqlファイルだと思います。
プラットフォームによって大文字と小文字を区別するかどうか変わりますので、テーブル名は小文字で揃えておいた方がいいと思います。
詳しくは9.2.2 識別子の大文字と小文字の区別をご確認ください。

変更前

CREATE TABLE IF NOT EXISTS Account(
    id int auto_increment COMMENT 'ユーザID',
    email VARCHAR(255) NOT NULL COMMENT 'メールアドレス',
    password VARCHAR(255) NOT NULL COMMENT 'パスワード',
    unique index (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Insert into Account(email, password) values(‘xxxx’,’xxxx’);

変更後

  • テーブル名を小文字にしました。
  • プライマリキーを定義しました。JPAではプライマリキーは必要です。
  • insert文のvaluesで指定されている文字列をシングルクォートで囲むように修正しました。(変更前はシングルクォートではない文字が使われていたので実行時にエラーになります。)
CREATE TABLE IF NOT EXISTS account(
    id int auto_increment COMMENT 'ユーザID',
    email VARCHAR(255) NOT NULL COMMENT 'メールアドレス',
    password VARCHAR(255) NOT NULL COMMENT 'パスワード',
    primary key (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

insert into account(email, password) values ('xxxx', 'xxxx');

AccountEntity.java

変更前

@Entity
@Table(name = "Account")
@Data
public class AccountEntity {

    @Column
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column
    private String email;

    @Column
    private String password;


}

変更後

  • テーブル名を小文字にしました。
  • Idカラムに対してColumnアノテーションは不要です。(付いていてもエラーにはなりません)
@Entity
@Table(name = "account")
@Data
public class AccountEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column
    private String email;

    @Column
    private String password;

}

application.properties

問題はありませんが気になった点があったので、参考までに記載させて頂きます。(こう書かないといけないということではありません)

変更前

spring.datasource.url=jdbc:mysql://localhost:3306/demo?characterEncoding=UTF-8&serverTimezone=JST 
spring.datasource.username=root
spring.datasource.password=p@ssw0rd
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.database=MYSQL
spring.jpa.hibernate.ddl-auto=update

変更後

  • spring.datasource.driver-class-nameとspring.jpa.databaseを削除しました。このプロパティは基本的にSpring Bootの自動設定に任せてた方がいいとおもいます。
spring.datasource.url=jdbc:mysql://localhost:3306/demo?characterEncoding=UTF-8&serverTimezone=JST 
spring.datasource.username=root
spring.datasource.password=p@ssw0rd
spring.jpa.hibernate.ddl-auto=update

build.gradle

問題はありませんが気になった点があったので、参考までに記載させて頂きます。(書き方は統一しておいた方がいいと思いました。)
こちらの記事Gradle の compile, api, implementation とかについてで解説されているので気になったら読んでみてください。

変更前

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    runtimeOnly 'org.springframework.boot:spring-boot-devtools'
    compileOnly 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    // mysql database
    //compile "mysql:mysql-connector-java"
    //compile "org.flywaydb:flyway-core"
    //compile "org.springframework.boot:spring-boot-starter-security"
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    //compile('mysql:mysql-connector-java')
    runtime('mysql:mysql-connector-java')

}

変更後

  • 依存関係の指定で新しい書き方と古い書き方が混在していたので新しい書き方へ統一しました。
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    runtimeOnly 'mysql:mysql-connector-java'
    runtimeOnly 'org.springframework.boot:spring-boot-devtools'
    compileOnly 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

問題の切り分け

どこに問題があるのか切り分けを行ううえで、dockerのMySQLにログインしてデータベースの状態を確認することも有効です。
次のコマンドでMySQLにログインできます。

docker-compose exec mysql mysql -u root -pp@ssw0rd
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.14 MySQL Community Server - GPL

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| demo               |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

mysql> use demo
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+----------------+
| Tables_in_demo |
+----------------+
| account        |
+----------------+
1 row in set (0.00 sec)

mysql> select * from account;
+----+-------+----------+
| id | email | password |
+----+-------+----------+
|  1 | xxxx  | xxxx     |
+----+-------+----------+
1 row in set (0.00 sec)

もし上手くいかなかったら、dockerのコンテナを作り直すところからやり直してみてください。
そのとき、ローカル上に保存しているMySQLのデータ領域も削除したほうがいいかもしれませんが、消したくないデータもあるかと思いますので、ご自身の判断で行ってください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/03 00:33

    ありがとうございます。無事、dockerで作成したmysql環境で連携確認ができました。
    sqlファイルのテーブル定義とinsertが間違っており、内部でエラーが出ていたことが主因と認識しました。他にもbuild.gradleの書き方やapplication.propertiesの書き方も勉強になりました。
    今のうちにどこかの記事にアウトプットしたいと思います。
    2週間悩んでいたので大変勉強になりました。ありがとうございます。

    キャンセル

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

  • ただいまの回答率 87.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る