Java CSVからのデータを表示させる（spring boot）

#プロローグ

Java（spring boot）を触り始めてコードを書き始めて２週間程度ですが、
色々と使い方を覚えてきたので、メモとして記録を残します。

不備不足だったり、理解が浅くて説明不足なところがあるかと思いますが、
勉強して更新していきたいとは思っています。

このプログラミングを書く前の理解度としては、アノテーションも分からずでした。
spring bootも分からなかったので、Ruby on Railsと同じようにMVCでデータを取得、加工、表示するのかなと思っていました。

計算処理を行う「service」というものの存在も知りませんでした。

##この記事で何ができるようになるか

まだ自分自身もそれぞれのクラスの役割を理解してませんが、
データを受け取って表示させることができると思います。

まずは、わからないなりに手を動かして画面に表示させることで、なんとなくの流れをつかむことが大切なのかなと思います。

この記事でやることとしては、ファイル内に作成したCSVファイルを読み取って、画面上に表示させるというイメージです。

また、ただ読み取って表示させるだけではなく、合計点を算出していきたいと思います。

##Javaの構造把握

まずは、ファイルの構造を紹介していきます。

```java:file

src/main/java
　├ resources
  ├ └ files
  ├    └ scores.csv
  ├ └ templates
  ├    └ score.html
  ├    └ score
  ├      └ total.html
　├ repository
　├  └ ScoreCsvRepository.java
  ├ entity
　├  └ ScoreEntity.java
  ├ serivice
　├  └ ScoreService.java
  ├ dto
　├  └ ScoreDto.java
  └ controller
　   └ ScoreController.java

```

###1.CSV

` resources/files/scores.csv` にあるデータをHTMLまでもっていき画面上に出したいとします。
CSVに下記のようなデータがあるとします。

```csvs:scores.csv
name,english,math,
山田,50,38
田中,30,47
高橋,64,58
鈴木,NA,94
石井,74,28
坂本,73,85
```
これをイメージとしては下記画像のようにデータを渡していきます。
この記事では、「加工したデータ」というのはenglishとmathの合計点を算出したもの、とします。

![スクリーンショット (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664818/deb522fd-310d-0285-8f5c-99592f72887d.png)


フレームワークによってmodelの定義が異なるみたいです。
勉強になります・・。

【参考文献】
[Webアプリケーション開発者から見た、MVCとMVP、そしてMVVMの違い](https://qiita.com/shinkuFencer/items/f2651073fb71416b6cd7)

###2.Repository

Repositoryでは、CSVのデータをとってきます。
CSVデータだけではなく、DBからデータをとってくることもできます。

とってきたデータをEntityという入れ物に入れますが、
その時にどこのどのデータを入れるか、をここで書いていきます。

```java:scoreRepository.java
package repository;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;

import pg.skilltest.entity.ScoreEntity;

public class ScoreCsvRepository {
    public List<ScoreEntity> getAllScores() {
        var result = new ArrayList<ScoreEntity>();
        //resultは、ArrayListで作成したデータと定義しています。

        BufferedReader br = null;
        String score_csv = "src/main/resources/files/scores.csv";
　　　　// 読み込みたいCSVファイルを指定します。
        try {
            File file = new File(score_csv);
            br = new BufferedReader(new FileReader(file));
            String line;
            String[] data;
            br.readLine();
　　　　　　//CSVデータの1行目は見るとわかるのですが、「name,english,math」となっています。
　　　　　　//この先のコードでenglishとmathの合計点を出したいので、タイトルの１行目を飛ばすために、
　　　　　　//「br.readLine();」とここで書くと１行目は計算されず読み込まれます。
            while ((line = br.readLine()) != null) {
                data = line.split(",");
                var scoreEntity = new ScoreEntity();
                //ここの「setGroup」などは、例えば「setGroup」の場合
　　　　　　　 　//（data[0])を次のEntityに入れる棚のgroupという名前に入れるというのを示しています（わかりにくい…）
                scoreEntity.setName(data[0]);
                if(data[1].equals("NA") == false) {
                    scoreEntity.setEnglish(Integer.parseInt(data[1]));
                    scoreEntity.setMath(Integer.parseInt(data[2]));
                } else {
                    scoreEntity.setEnglish(0);
                    scoreEntity.setMath(0);
                }
                result.add(scoreEntity);
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        } finally {
            try {
                br.close();
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
        return result;
    }
}

```

CSVの読み込みは、下記の記事を参考に書きました。
ありがとうございます。

【参考文献】
[JavaでのCSVファイル読み込み方法とは？](https://www.fenet.jp/java/column/java_tips/3760/)

###3.Entity

Repositoryで記載した「getName」などはここと連動しています。
つまり、`.getName(data[0])`と書いたら、`data[0]`が下記の`name`に入っていくイメージです。
`@Data`に関しては、便利だ！と思って使っていますが、よくわかっていないので、
`@Data`なしでも書けるように便利なものも調べておきます・・。
（`getName`とやってEntityにデータが入っていくのも`@Data`のおかげです）


```java:ScoreEntity.java
package entity;

import lombok.Data;

@Data
public class ScoreEntity {
    private String name;
    private Integer english;
    private Integer math;
}
```

###4.Servic

Serviceでは、Entityにいれたデータをもってきて、加工します。

```java:ScoreService.java
package service;

import java.util.ArrayList;
import java.util.List;

import dto.ScoreDto;
import repository.ScoreCsvRepository;

public class ScoreService {
    public List<ScoreDto> getAllTotalScores() {
        var result = new ArrayList<ScoreDto>();
        var scoreCsvRepository = new ScoreCsvRepository();
        var allScore = scoreCsvRepository.getAllScores();

        for (int i = 0; i < allScore.size(); i++) {
            var score = allScore.get(i);
            var total = score.getEnglish() + score.getMath();
            var name = score.getName();
            var scoreDto = new ScoreDto();
　　　　　　//Entityの時と同じように、Dtoにそれぞれの値をいれています。
            scoreDto.setTotal(total);
            scoreDto.setName(name);

            result.add(scoreDto);
        }
        return result;
    }

}

```

###5.Dto

Integer など最初を大文字にすると、その値がnullの場合も入ります。
ここあたりも知らないことあるので、深堀したいです…。

```java:ScoreDto.java
package dto;

import lombok.*;

@Data
public class ScoreDto {
    private String name;
    private Integer total;
}
```

###6.Controller

```java:ScoreController.java
package controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;


import service.ScoreService;


@Controller
public class ScoreController {

  // 得点一覧画面
	@RequestMapping("/score")
	public String index() {
		return "score";
	}
	
  //　合計画面
	@RequestMapping("/score/total")
	public String total(Model model) {
		var scoreService = new ScoreService();
		model.addAttribute("result", scoreService.getAllTotalScores());
                // `.getAllTotalScores()`がServiceで記載してあるのと一致しています。
　　　　　　　　　//その値を`result`に入れています。そしてHTMLに渡しています。
		
		return "score/total";
	}
}
```

###7.HTML

かなりざっくりですが、下記のように記載すれば、controllerからデータを受け取ることができます。
この書き方はThymeleafと呼ばれるものです。
あまり書いたことないので、（これがはじめて）ここも勉強していかないとです…。

```HAML:total.html

【結果】
    <p th:each="totalDto : ${result}">
　　<!--Controllerの`result`をここで呼び出してeachで回しています。-->
      <span th:text="${totalDto.name}"></span>
　　<!-- Dtoで定義した`name`を呼び出しています。-->
      <span th:text="${totalDto.total}"></span>
    </p>

```

####終わりに

なんとなくJSと似ているところがあったりして、初めてプログラミングを学んだ時より理解はありましたが、
MVCだけではないクラスを使ってデータを加工するというのが初めてだったので、戸惑いがありました。

ただ、かなり整理されて作ることができるので、わかりやすいなと思いました。
まだまだなところや間違っていることがあるかと思いますので、勉強して更新していきたいです。