spring boot 自分用メモ crossfish21 6_10

メモ

```
useradd jinkenhi  でユーザ「jinkenhi」を追加

passwd jinkenhi  で、jinkenhiのパスワードを設定する
pass は"blackAzarashi21"

psql --version　でバージョン確認

sudo /usr/pgsql-10/bin/postgresql-10-setup initdb　でDB初期化
Initializing database ... OK　と表示されるはず

systemctl start postgresql-10.service　　でサービス起動

systemctl enable postgresql-10.service　　で自動起動するように設定

sudo passwd postgres　　で、「postgres」ユーザの新しいパスワードを設定
"brownAzarashi21"  にしておく

su - postgres    で、「postgres」ユーザとしてDBにログイン
-bash-4.2$　　というプロンプトになっているはず

psql    でDBへ接続する。これで標準で用意されているデータベース「postgres」に接続する
postgres=#　　というプロンプトになっているはず(postgresがDB名。接続するDBごとに変わってくる)






psql -U postgres  でスーパーユーザでログイン

create role jinkenhi with login createdb replication password 'blackAzarashi21';
でユーザ作成






サーバーでの起動手順
https://qiita.com/AkihiroTakamura/items/e1be1a70428c57b10f8b

https://ishiis.net/2016/09/27/spring-boot-init-script/





POIの非推奨を修正

if (cell01 == null || cell01.getCellTypeEnum() == CellType.BLANK) {
// これで空白かどうかを判断できる。nullチェックは必要なのか?
    System.out.println("セル" + cell01.getAddress() + "は空白");
}else{
    String str1 = cell01.getStringCellValue();
    System.out.println(str1);
}




※※※※　　実績値のCSVファイルは、UTF-8のBOM無しにしないとだめ

update　には
    @Modifying //Updateに必要
    @Query("update HogeEntity h set " //"hogeEntity AS h set"でも"hogeEntity set"でもOK未実行
    

```
---





controller

```
  @RequestMapping(value = "company_staff_overtime_result_register_execute",method = RequestMethod.POST)
  public String companyStaffOvertimeResultRegisterExecute(
      @RequestParam("upFile") MultipartFile upFile,
      @RequestParam("flag") String flag,
      Model model) {

    if (upFile.isEmpty()) {
      // ファイルがアップされていない場合
      model.addAttribute("errorMessage", "ファイルが指定されていません");
      return "company_staff_overtime_register";
    }

    CompanyStaffOvertimeResultBean companyStaffOvertimeResultBean =
    	companyStaffOvertimeResultRegisterService.getompanyStaffOvertimeResult(upFile);

    if(companyStaffOvertimeResultBean.getErrorMessageList().size() > 0) {
    // エラーが発生している場合
    	// TODO エラーメッセージを返す
    }

    List<String> staffNoAndYearList = companyStaffOvertimeResultBean.getStaffNoAndYearList();
    // 従業員Noと年度を連結した文字列のリスト
    int dataCount;  // データ存在確認用
    String staffNo;
    Integer year;

    for(int i=0; i<staffNoAndYearList.size(); i++) {
    	staffNo = staffNoAndYearList.get(i).substring(0, 9);
    	year = Integer.parseInt(staffNoAndYearList.get(i).substring(9, 13));
    	dataCount = companyStaffOvertimeResultTransactionService.getDataCount(staffNo,year);
    	if(dataCount == 0) {
    	// データがまだ存在していない場合
    		companyStaffOvertimeResultTransactionService.insert(staffNo, year);
    		// 新規レコードを作成
    	}
    }


    List<MonthDataBean> dataList = companyStaffOvertimeResultBean.getDataList();
    Integer month;  // 4月
    Double overtime;  // 時間外時間

    for(int i=0; i<dataList.size(); i++) {

		month = dataList.get(i).getMonth();
		staffNo = dataList.get(i).getStaffNo();
		year = dataList.get(i).getYear();

		if(flag.equals("true")) {
		// 裁量勤務者の場合
			overtime = dataList.get(i).getHealthControllTime() - dataList.get(i).getHolidayWorkTime();
		}else {
			overtime = dataList.get(i).getOvertime() - dataList.get(i).getHolidayWorkTime();
		}

		switch(month) {
		case 4:
			companyStaffOvertimeResultTransactionService.updateOvertime4(overtime, staffNo, year);
		default:
			System.out.println("4以外");
		}
    }
    return "company_staff_overtime_register";
  }
```
---

Repository

```
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import com.crossfish.entity.CompanyStaffOvertimeResult;
import com.crossfish.entity.CompanyStaffOvertimeResultKey;

public interface CompanyStaffOvertimeResultRepository
    extends JpaRepository<CompanyStaffOvertimeResult, CompanyStaffOvertimeResultKey> {

  // データ数を取得して、データの存在を確認する
  @Query(value = "SELECT Count(*) staff_no FROM company_staff_overtime_result "
  		+ "WHERE staff_no=:StaffNo AND year=:year", nativeQuery = true)
  public int getDataCount(
		@Param("StaffNo")String StaffNo,
	    @Param("year")Integer year);


  @Query(value = "UPDATE company_staff_overtime_result SET overtime4=:overtime4 "
		  + "WHERE staff_no=:StaffNo AND year=:year", nativeQuery = true)
  public void updateOvertime4(
		  @Param("overtime4")Double overtime4,
		  @Param("StaffNo")String StaffNo,
		  @Param("year")Integer year);
}
```
---
Service

```
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.crossfish.componet.CompanyStaffOvertimeResultBean;
import com.crossfish.componet.MonthDataBean;

@Service
public class CompanyStaffOvertimeResultRegisterService {

	public CompanyStaffOvertimeResultBean getompanyStaffOvertimeResult(MultipartFile upFile) {

		MultipartFile upFile2 = upFile;

		CompanyStaffOvertimeResultBean returnBean = new CompanyStaffOvertimeResultBean();
		List<String> errorMessageList = new ArrayList<String>();
		// エラーメッセージのリスト

		String[] rawDataArray;  // 全読込みしたデータの配列
		MonthDataBean monthDataBean;   // 月ごとのデータを格納するBean
		List<MonthDataBean> monthDataList = new ArrayList<>();

		String staffNoAndYear;  // 従業員Noと年度を繋げた文字列
		List<String> staffNoAndYearList = new ArrayList<>();  // 従業員Noと年度を繋げた文字列を格納するリスト

		String staffNo;  // 従業員No
		String year;  // 年
		String month; // 月
		String day;  // 日
		Double overtime;  // 時間外時間
		Double healthControllTime;  // 健康管理時間
		Double holidayWorkTime;  // 休日出勤時間

		String beforeStaffNo = "aaa";  // 1つ前の行の従業員No
		String beforeYear = "";  // 1つ前の行の年
		String beforeMonth = "";  // 1つ前の行の月
		Double totalOvertime = 0.0;  // 時間外時間の合計値
		Double totalHealthControllTime = 0.0;  // 健康管理時間の合計値
		Double totalHolidayWorkTime = 0.0;  // 休日出勤時間の合計値

		int rowNumber = 1;  //現在読み込んでいる行番号
		String  regrex = "7Y4[0-9]{6}"; // 従業員Noをチェックする正規表現
		Pattern pattern = Pattern.compile(regrex);
		Matcher matcher;
		Double tempDouble;

	    try (FileInputStream input = (FileInputStream) upFile.getInputStream();
	    	 FileInputStream input2 = (FileInputStream) upFile.getInputStream();
	    	    BufferedReader reader1 = new BufferedReader(new InputStreamReader(input));
	    		BufferedReader reader2 = new BufferedReader(new InputStreamReader(input2));){

	        String line;
	        Integer rowCount = 0;  // 行数カウント用
	        while ((line = reader1.readLine()) != null) {
	        // 行数を取得するために、一度全行を読込みする
	        	rowCount++;
	        }


	        while ((line = reader2.readLine()) != null) {
	        // 1行ずつCSVファイルを読み込む

	          rawDataArray = line.split(",", 0); // 行をカンマ区切りで配列に変換

	          if(rawDataArray.length != 9) {
	          // 1行のデータ数が9ではない場合
	        	  errorMessageList.add(rowNumber + "行目目のデータ数が異常です");
	        	  returnBean.setErrorMessageList(errorMessageList);
	        	  return returnBean;
	          }

	          // 従業員No
	          staffNo = rawDataArray[0];
	          matcher = pattern.matcher(staffNo);
	          if(!matcher.find()) {
	          // 正規表現にマッチしない場合
	        	  errorMessageList.add(rowNumber + "行目目の従業員Noが異常です");
	        	  returnBean.setErrorMessageList(errorMessageList);
	        	  return returnBean;
	          }

	          // 日付
	          if(rawDataArray[2].length() >= 8) {
	        	  LinkedList<String> dateList = getDate(rawDataArray[2]);
	        	  // 年・月・日の値を格納したリスト
	        	  if(dateList == null) {
		        	  errorMessageList.add(rowNumber + "行目目の日付が異常です");
		        	  returnBean.setErrorMessageList(errorMessageList);
		        	  return returnBean;
	        	  }
	        	  year = dateList.get(0);
	        	  month = dateList.get(1);
	        	  day = dateList.get(2);
	          }else {
	        	  errorMessageList.add(rowNumber + "行目目の日付が異常です");
	        	  returnBean.setErrorMessageList(errorMessageList);
	        	  return returnBean;
	          }

	          // 時間外時間
	          tempDouble = parseToDouble(rawDataArray[4]);
	          if(Double.compare(tempDouble, -9999.99) == 0) {
	          // 数値に変換出来なかった場合
	        	  errorMessageList.add(rowNumber + "行目目の時間外時間が異常です");
	        	  returnBean.setErrorMessageList(errorMessageList);
	        	  return returnBean;
	          }else {
	        	  overtime = tempDouble;
	          }

	          // 健康管理時間
	          tempDouble = parseToDouble(rawDataArray[5]);
	          if(Double.compare(tempDouble, -9999.99) == 0) {
	        	  // 数値に変換出来なかった場合
	        	  errorMessageList.add(rowNumber + "行目目の健康管理時間が異常です");
	        	  returnBean.setErrorMessageList(errorMessageList);
	        	  return returnBean;
	          }else {
	        	  healthControllTime = tempDouble;
	          }

	          // 休日出勤時間
	          tempDouble = parseToDouble(rawDataArray[7]);
	          if(Double.compare(tempDouble, -9999.99) == 0) {
	        	  // 数値に変換出来なかった場合
	        	  errorMessageList.add(rowNumber + "行目目の休日出勤時間が異常です");
	        	  returnBean.setErrorMessageList(errorMessageList);
	        	  return returnBean;
	          }else {
	        	  holidayWorkTime = tempDouble;
	          }

	          if(rowNumber == 1 || beforeStaffNo.equals(staffNo)) {
	          // 1行目の場合
	        	  totalOvertime = totalOvertime + overtime;
	        	  totalHealthControllTime = totalHealthControllTime + healthControllTime;
	        	  totalHolidayWorkTime = totalHolidayWorkTime + holidayWorkTime;

	          }else {
	          // 他の従業員のデータに切り替わった場合
	        	  monthDataBean = new MonthDataBean();
	        	  monthDataBean.setStaffNo(beforeStaffNo);
	        	  monthDataBean.setYear(Integer.parseInt(beforeYear));
	        	  monthDataBean.setMonth(Integer.parseInt(beforeMonth));
	        	  monthDataBean.setOvertime(totalOvertime);
	        	  monthDataBean.setHealthControllTime(totalHealthControllTime);
	        	  monthDataBean.setHolidayWorkTime(totalHolidayWorkTime);
	        	  monthDataList.add(monthDataBean);

	        	  staffNoAndYear = beforeStaffNo + beforeYear;
	        	  // 従業員Noと年度を繋げた文字列
	        	  if(!staffNoAndYearList.contains(staffNoAndYear)) {
	        		  staffNoAndYearList.add(staffNoAndYear);
	        	  }

	        	  totalOvertime = overtime;
	        	  totalHealthControllTime = healthControllTime;
	        	  totalHolidayWorkTime = holidayWorkTime;
	          }

	          if(rowNumber == rowCount) {
	          // 最後の行まで来た場合
	        	  monthDataBean = new MonthDataBean();
	        	  monthDataBean.setStaffNo(staffNo);
	        	  monthDataBean.setYear(Integer.parseInt(year));
	        	  monthDataBean.setMonth(Integer.parseInt(month));
	        	  monthDataBean.setOvertime(totalOvertime);
	        	  monthDataBean.setHealthControllTime(totalHealthControllTime);
	        	  monthDataBean.setHolidayWorkTime(totalHolidayWorkTime);
	        	  monthDataList.add(monthDataBean);

	        	  staffNoAndYear = staffNo + year;
	        	  // 従業員Noと年度を繋げた文字列
	        	  if(!staffNoAndYearList.contains(staffNoAndYear)) {
	        		  staffNoAndYearList.add(staffNoAndYear);
	        	  }
	          }

	          beforeStaffNo = staffNo;
	          // 現在の従業員Noを1行前のデータとして保存
	          beforeYear = year;
	          beforeMonth = month;
	          rowNumber++;
	        }

		} catch (Exception e) {
			e.printStackTrace();
		}

	    if(monthDataList.size() == 0) {
	    // データが全く無かった場合
      	  errorMessageList.add("有効なデータが全くありません");
      	  returnBean.setErrorMessageList(errorMessageList);
      	  return returnBean;
	    }

	    returnBean.setDataList(monthDataList);
	    returnBean.setStaffNoAndYearList(staffNoAndYearList);

		return returnBean;
	}



    private LinkedList<String> getDate(String str1) {

    	LinkedList<String> dateList = new LinkedList<>();

    	String[] array1 = str1.split("/",0);
    	if(array1.length < 2) {
    	// "/"が2つ含まれない場合
    		return dateList;
    		// 何も格納しないでリターンする
    	}

    	try {
			int tempInt = Integer.parseInt(array1[0]);
			// 数値に変換する
			tempInt = Integer.parseInt(array1[1]);
			tempInt = Integer.parseInt(array1[2]);

			// ここまで例外発生しないならOK
			dateList.add(array1[0]);
			dateList.add(array1[1]);
			dateList.add(array1[2]);
			// 年・月・日の値を格納する

		} catch (NumberFormatException e) {
    		return dateList;
    		// 数値変換に失敗した場合は、何も格納しないでリターンする
		}
    	return dateList;
    }


    private Double parseToDouble(String str1) {

    	Double returnValue = -9999.99;
    	try {
    		returnValue = Double.parseDouble(str1);
			// 数値に変換する。例外発生しないならOK
			return returnValue;

		} catch (NumberFormatException e) {
    		return returnValue;
    		// 数値変換に失敗した場合は、そのままでリターンする
		}
    }

}
```
---
Component

```
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import lombok.Data;

@Data
public class CompanyStaffOvertimeResultBean implements Serializable {

	private List<MonthDataBean> dataList;
	private List<String> staffNoAndYearList;
	private List<String> errorMessageList;

	public CompanyStaffOvertimeResultBean() {
		dataList = new ArrayList<MonthDataBean>();
		staffNoAndYearList = new ArrayList<String>();
		errorMessageList = new ArrayList<String>();
	}
}



import java.io.Serializable;

import org.springframework.stereotype.Component;

import lombok.Data;

@Component
@Data
public class MonthDataBean implements Serializable {

	private String staffNo;
	private Integer year;
	private Integer month;
	private Double overtime;
	private Double healthControllTime;
	private Double holidayWorkTime;

	public MonthDataBean() {
		staffNo = "";
		year = 0;
		month = 0;
		overtime = 0.0;
		healthControllTime = 0.0;
		holidayWorkTime = 0.0;
	}
}
```