src/main/resources/config messages_ja.properties
# バリデーションエラー時のメッセージ設定
javax.validation.constraints.NotEmpty.message={0}は入力必須です
javax.validation.constraints.NotNull.message={0}は入力必須です
javax.validation.constraints.Min.message={0}は{1}以上にしてください
javax.validation.constraints.Max.message={0}は{1}以下にしてください
# DecimalMax と DecimalMin は{2}が指定の数値になるので注意
javax.validation.constraints.DecimalMax.message={0}は{2}以下にしてください
javax.validation.constraints.DecimalMin.message={0}は{2}以下にしてください
javax.validation.constraints.Digits.message={0}の整数部と小数部の桁数が正しくありません
javax.validation.constraints.Email.message={0}はEメール形式にしてください
javax.validation.constraints.Future.message={0}は未来の日付で入力してください
javax.validation.constraints.Past.message={0}は過去の日付で入力してください
javax.validation.constraints.Pattern.message={0}は指定のパターンにマッチしません
# Size Length Range は{2}がminの値、{1}がmaxの値になるので注意
javax.validation.constraints.Size.message={0}の文字列長は{2}~{1}の範囲にしてください
org.hibernate.validator.constraints.Length.message={0}の文字列長は{2}~{1}の範囲にしてください
org.hibernate.validator.constraints.Range.message={0}は{2}~{1}の数値にしてください
# 型変換に失敗した場合のエラーメッセージ設定
typeMismatch={0}を変換できません
typeMismatch.int={0}を数値に変換できません
typeMismatch.double={0}を数値に変換できません
typeMismatch.float={0}を数値に変換できません
typeMismatch.long={0}を数値に変換できません
typeMismatch.short={0}を数値に変換できません
typeMismatch.java.lang.Integer={0}を数値に変換できません
typeMismatch.java.lang.Double={0}を数値に変換できません
typeMismatch.java.lang.Float={0}を数値に変換できません
typeMismatch.java.lang.Long={0}を数値に変換できません
typeMismatch.java.lang.Short={0}を数値に変換できません
typeMismatch.java.math.BigDecimal={0}を数値に変換できません
typeMismatch.java.math.BigDecimal={0}を数値に変換できません
typeMismatch.java.math.BigInteger={0}を数値に変換できません
typeMismatch.java.time.LocalDate={0}を日付に変換できません
typeMismatch.java.time.LocalDateTime={0}をタイムスタンプに変換できません
typeMismatch.java.time.LocalTime={0}を時刻に変換できません
src/main/resources/config messages.properties
message.text01=MESSAGE_TEXT01
message.text02=MESSAGE_TEXT02
message.text03=MESSAGE_TEXT03
message.text04=\u65E5\u672C\u8A9E\u30E1\u30C3\u30BB\u30FC\u30B8
src/main/resources/static/css base.css
# wrapper{
padding: 100px;
}
h3{
margin-bottom: 25px;
}
src/main/resources/ application.properties
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/hsystem?currentSchema=schemah
spring.datasource.username=role21
spring.datasource.password=yellowAzarashi21
server.port=8091
spring.messages.basename=config/messages
spring.messages.cache-duration=-1
spring.messages.encoding=UTF-8
spring.thymeleaf.prefix=classpath:/page/
spring.thymeleaf.mode=HTML
spring.thymeleaf.cache=false
# spring.thymeleaf.cache=falseにすると、テンプレートの変更がアプリの再起動をしなくても反映される。ただし、本番では必ずtrueにすること
spring.thymeleaf.cache=false
spring.jpa.show-sql=true
src/main/resources/ hibernate.properties
hibernate.jdbc.lob.non_contextual_creation = true
com.crossfish.p1.config MessageConfig.java
package com.crossfish.p1.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@SuppressWarnings("deprecation")
@Configuration
public class MessageConfig extends WebMvcConfigurerAdapter{
@Autowired
private MessageSource messageSource;
@Bean
public LocalValidatorFactoryBean validator()
{
LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
localValidatorFactoryBean.setValidationMessageSource(messageSource);
return localValidatorFactoryBean;
}
@Override
public Validator getValidator()
{
return validator();
}
}
com.crossfish.p1.controller PageController.java
package com.crossfish.p1.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("page")
public class PageController {
@RequestMapping("main_menu")
public String mainMenu() {
return "/page/main_menu";
// メンメニューへ
}
@RequestMapping("outsourcing_worktime_register")
public String outsourcingWorktime() {
return "/page/outsourcing_worktime_register";
// 外注者の稼働時間登録画面へ
}
}
com.crossfish.p1.controller RegisterController.java
package com.crossfish.p1.controller;
import java.io.InputStream;
import javax.servlet.http.HttpSession;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
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 org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import com.crossfish.p1.services.OutsourcingWorkingTimeServiceReadOnly;
import com.crossfish.p1.services.OutsourcingWorkingTimeServiceTransaction;
/*
* @author Benten
* DBへデータを登録する処理のコントローラー
*/
@Controller
@RequestMapping("register")
public class RegisterController {
@Autowired
HttpSession session;
@Autowired
private OutsourcingWorkingTimeServiceTransaction outsourcingWorkingTimeServiceTransaction;
@Autowired
private OutsourcingWorkingTimeServiceReadOnly outsourcingWorkingTimeServiceReadOnly;
/*
* @param multipartFile アップされたファイル
* @param model Modelインスタンス
* @return String 移動先のページのパス
*/
@RequestMapping(value = "outsourcing_worktime_register_execute",method = RequestMethod.POST)
public String outsourcingWorktimeRegisterExecute(
@RequestParam("file01") MultipartFile multipartFile, Model model) {
if (multipartFile.isEmpty()) {
// ファイルがアップされていない場合
model.addAttribute("errorMessage", "ファイルが指定されていません");
return "/page/outsourcing_worktime_register";
}
Integer int1 = outsourcingWorkingTimeServiceReadOnly.getLastRivisionNumber("2018年度予算", "001");
outsourcingWorkingTimeServiceTransaction.insert();
try (InputStream input = multipartFile.getInputStream()) {
try (XSSFWorkbook outsourcingWorktimeBook = (XSSFWorkbook) WorkbookFactory.create(input)) {
XSSFSheet targetSheet = outsourcingWorktimeBook.getSheet("外注者の稼働時間");
if (targetSheet == null) { // シートが取得できなかった場合
System.out.println("シートの取得に失敗");
}
String departmentString = ""; // 所属部署の18桁コード
String versionString = ""; // バージョン名
Row row03 = targetSheet.getRow(2); // 3行目を取得
Cell cell01 = row03.getCell(5);
if (cell01.getCellTypeEnum() != CellType.BLANK
&& cell01.getCellTypeEnum() == CellType.STRING) {
// 一応文字列型であることと、空白でないことをチェック
departmentString = cell01.getStringCellValue();
}
Row row05 = targetSheet.getRow(4); // 3行目を取得
cell01 = row05.getCell(2);
versionString = cell01.getStringCellValue();
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
return "/page/outsourcing_worktime_register";
}
}
com.crossfish.p1.entities OutsourcingWorkingTime.java
package com.crossfish.p1.entities;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.Table;
import lombok.Data;
@Entity
@Data
@IdClass(value = OutsourcingWorkingTimeKey.class) // コメント
@Table(name = "outsourcing_working_time",schema="schemah")
public class OutsourcingWorkingTime implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "version_name")
private String versionName;
@Id
@Column(name = "department_code")
private String departmentCode;
@Id
@Column(name = "revision")
private Integer revision;
@Id
@Column(name = "staff_no")
private String staffNo;
@Column(name = "staff_name")
private String staffName;
@Column(name = "company_name")
private String companyName;
@Column(name = "basetime_4")
private Double basetime4;
@Column(name = "overtime_4")
private Double overtime4;
@Column(name = "businessPlace_4")
private String businessPlace4;
@Column(name = "basetime_5")
private Double basetime5;
@Column(name = "overtime_5")
private Double overtime5;
@Column(name = "businessPlace_5")
private String businessPlace5;
@Column(name = "basetime_6")
private Double basetime6;
@Column(name = "overtime_6")
private Double overtime6;
@Column(name = "businessPlace_6")
private String businessPlace6;
@Column(name = "basetime_7")
private Double basetime7;
@Column(name = "overtime_7")
private Double overtime7;
@Column(name = "businessPlace_7")
private String businessPlace7;
@Column(name = "basetime_8")
private Double basetime8;
@Column(name = "overtime_8")
private Double overtime8;
@Column(name = "businessPlace_8")
private String businessPlace8;
@Column(name = "basetime_9")
private Double basetime9;
@Column(name = "overtime_9")
private Double overtime9;
@Column(name = "businessPlace_9")
private String businessPlace9;
@Column(name = "basetime_10")
private Double basetime10;
@Column(name = "overtime_10")
private Double overtime10;
@Column(name = "businessPlace_10")
private String businessPlace10;
@Column(name = "basetime_11")
private Double basetime11;
@Column(name = "overtime_11")
private Double overtime11;
@Column(name = "businessPlace_11")
private String businessPlace11;
@Column(name = "basetime_12")
private Double basetime12;
@Column(name = "overtime_12")
private Double overtime12;
@Column(name = "businessPlace_12")
private String businessPlace12;
@Column(name = "basetime_1")
private Double basetime1;
@Column(name = "overtime_1")
private Double overtime1;
@Column(name = "businessPlace_1")
private String businessPlace1;
@Column(name = "basetime_2")
private Double basetime2;
@Column(name = "overtime_2")
private Double overtime2;
@Column(name = "businessPlace_2")
private String businessPlace2;
@Column(name = "basetime_3")
private Double basetime3;
@Column(name = "overtime_3")
private Double overtime3;
@Column(name = "businessPlace_3")
private String businessPlace3;
}
com.crossfish.p1.entities OutsourcingWorkingTimeKey
package com.crossfish.p1.entities;
import java.io.Serializable;
import lombok.Data;
@Data
public class OutsourcingWorkingTimeKey implements Serializable {
// OutsourcingWorkingTimeエンティティの複合主キーを設定するクラス
private String versionName;
private String departmentCode;
private Integer revision;
private String staffNo;
}
com.crossfish.p1.repositories OutsourcingWorkingTimeRepository
package com.crossfish.p1.repositories;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import com.crossfish.p1.entities.OutsourcingWorkingTime;
import com.crossfish.p1.entities.OutsourcingWorkingTimeKey;
public interface OutsourcingWorkingTimeRepository
extends JpaRepository<OutsourcingWorkingTime, OutsourcingWorkingTimeKey> {
// 最終のリビジョン番号を取得する
@Query(value = "SELECT DISTINCT revision FROM outsourcing_working_time o WHERE version_name=:versionName AND "
+ "department_code=:departmentCode ORDER BY revision DESC LIMIT 1", nativeQuery = true)
// 先頭にvalue = を、末尾に, nativeQuery = trueをつける。valueはObject型になる。メソッドの戻り値として使える
// outsourcing_working_timeはテーブル名だが、Entityクラスの名前ではなくDBのテーブル名をそのまま記述することに注意
public Integer getLastRivisionNumber(
@Param("versionName")String versionName,
@Param("departmentCode")String departmentCode);
}
com.crossfish.p1.services OutsourcingWorkingTimeServiceReadOnly.java
package com.crossfish.p1.services;
public interface OutsourcingWorkingTimeServiceReadOnly{
public Integer getLastRivisionNumber(String versionName,String departmentCode);
}
com.crossfish.p1.services OutsourcingWorkingTimeServiceReadOnlyImple
package com.crossfish.p1.services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.crossfish.p1.repositories.OutsourcingWorkingTimeRepository;
@Service
@Transactional(readOnly = true)
public class OutsourcingWorkingTimeServiceReadOnlyImple implements OutsourcingWorkingTimeServiceReadOnly {
@Autowired
private OutsourcingWorkingTimeRepository outsourcingWorkingTimeRepository;
@Override
public Integer getLastRivisionNumber(String versionName,String departmentCode) {
Integer rivisionList = outsourcingWorkingTimeRepository.getLastRivisionNumber
(versionName, departmentCode);
return rivisionList;
}
}
com.crossfish.p1.services OutsourcingWorkingTimeServiceTransaction
package com.crossfish.p1.services;
public interface OutsourcingWorkingTimeServiceTransaction{
public void insert();
}
com.crossfish.p1.services OutsourcingWorkingTimeServiceTransactionImple
package com.crossfish.p1.services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.crossfish.p1.entities.OutsourcingWorkingTime;
import com.crossfish.p1.repositories.OutsourcingWorkingTimeRepository;
@Service
@Transactional(readOnly = false)
public class OutsourcingWorkingTimeServiceTransactionImple implements OutsourcingWorkingTimeServiceTransaction {
@Autowired
private OutsourcingWorkingTimeRepository outsourcingWorkingTimeRepository;
@Override
public void insert() {
OutsourcingWorkingTime outsourcingWorkingTime = new OutsourcingWorkingTime();
outsourcingWorkingTime.setVersionName("2018年度予算");
outsourcingWorkingTime.setDepartmentCode("002");
outsourcingWorkingTime.setRevision(4);
outsourcingWorkingTime.setStaffNo("7Y4001005");
outsourcingWorkingTime.setStaffName("高橋朝子");
outsourcingWorkingTime.setCompanyName("会社222");
outsourcingWorkingTime.setBasetime4(156.23);
outsourcingWorkingTime.setOvertime4(200.582);
outsourcingWorkingTime.setBusinessPlace4("事業所100");
outsourcingWorkingTime = outsourcingWorkingTimeRepository.saveAndFlush(outsourcingWorkingTime);
}
}
STSのコード
package p1.controller;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import p1.repository.R02;
import p1.repository.entity.Table01;
import p1.repository.entity.Table01.Sex;
import p1.service.S01;
import p1.service.S02;
@Controller
@RequestMapping("c01")
public class C01 {
@Autowired
private S01 s01; // S01はサービスクラス
@Autowired
private S02 s02;
@Autowired
private R02 r02; // R02はリポジトリ
@RequestMapping("01") // リポジトリを使わないで、テーブルのデータ一覧を取得
public String list01(Model model) {
model.addAttribute("table01Data", s01.getTable01List());
return "01/list01";
}
@RequestMapping("02") // リポジトリを使って、テーブルのデータ一覧を取得
public String list02(Model model) {
model.addAttribute("table01Data", s02.getTable01List());
return "01/list01";
}
@RequestMapping("03/{id}") // id指定で、1つのデータを取得。存在しないidを指定するとエラーになる
public String getOne(Model model,@PathVariable Integer id) {
model.addAttribute("table01Data", s02.getOne(id));
// getOne()は、サービスクラスに実装している
// id指定で、データを参照するEntityをリターンする。該当するデータが存在しない場合はエラー発生
return "01/list01";
}
@RequestMapping("04/{id}") // id指定で、1つのデータを取得。存在しないidを指定するとエラーになる
public String findById(Model model,@PathVariable Integer id) {
Optional<Table01> table01 = s02.findById(id);
// findById()は、サービスクラスに実装している
// id指定で、Entityをリターンする。該当するデータが存在しない場合はnullが返るのでOptionalにする
if(!table01.equals(Optional.empty())) { // データが存在する場合。.equals(Optional.empty())にすることに注意
model.addAttribute("table01Data", table01.get()); // .get()にすることに注意
return "01/list01";
}else {
return "error/error01";
}
}
@RequestMapping("05/{id1}/{id2}/{id3}") // 3つのid指定で、データを取得
// findAllById(List<Integer>) は、Postgresではエラーになってしまうらしい
public String multiId(Model model, @PathVariable Integer id1, @PathVariable Integer id2, @PathVariable Integer id3) {
List<Integer> idList = new ArrayList<>();
idList.add(id1);
idList.add(id2);
idList.add(id3);
model.addAttribute("table01Data", r02.findAllById(idList));
// findAllById()は、リポジトリに存在している
return "01/list01";
}
@RequestMapping("06/{id1}/{id2}") // idがid1~id2の範囲のデータを取得
public String betweenId(Model model, @PathVariable Integer id1, @PathVariable Integer id2) {
model.addAttribute("table01Data", r02.findByIdBetween(id1,id2));
return "01/list01";
}
@RequestMapping("07/{firstName}") // firstNameで検索(完全一致)
public String firstName(Model model, @PathVariable String firstName) {
model.addAttribute("table01Data", r02.findByFirstName(firstName));
return "01/list01";
}
@RequestMapping("08/{str}") // firstNameにstrが含まれるデータを検索(firstName like %str% になる)
public String findByFirstNameContains(Model model, @PathVariable String str) {
model.addAttribute("table01Data", r02.findByFirstNameContains(str));
return "01/list01";
}
@RequestMapping("17/{str}") // firstNameにstrが含まれないデータを検索(firstName not like %str% になる)
public String findByFirstNameNotContains(Model model, @PathVariable String str) {
model.addAttribute("table01Data", r02.findByFirstNameNotContains(str));
return "01/list01";
}
@RequestMapping("33/{str}") // firstNameがstrで始まるデータを検索(firstName like str% になる)
public String findByFirstNameStartsWith(Model model, @PathVariable String str) {
model.addAttribute("table01Data", r02.findByFirstNameStartsWith(str));
return "01/list01";
}
@RequestMapping("34/{str}") // firstNameがstrで終わるデータを検索(firstName like %str になる)
public String findByFirstNameEndsWith(Model model, @PathVariable String str) {
model.addAttribute("table01Data", r02.findByFirstNameEndsWith(str));
return "01/list01";
}
@RequestMapping("09/{id}/{firstName}") // idとfirstNameのAND条件で検索
public String findByIdAndFirstName(Model model, @PathVariable Integer id, @PathVariable String firstName) {
model.addAttribute("table01Data", r02.findByIdAndFirstName(id,firstName));
return "01/list01";
}
@RequestMapping("10/{id}/{firstName}") // idとfirstNameのOR条件で検索
public String findByIdOrFirstName(Model model, @PathVariable Integer id, @PathVariable String firstName) {
model.addAttribute("table01Data", r02.findByIdOrFirstName(id,firstName));
return "01/list01";
}
@RequestMapping("11/{id}") // idが~未満の条件で検索
public String findByIdLessThan(Model model, @PathVariable Integer id) {
model.addAttribute("table01Data", r02.findByIdLessThan(id));
return "01/list01";
}
@RequestMapping("12/{id}") // idが~より大きいの条件で検索
public String findByIdGreaterThan(Model model, @PathVariable Integer id) {
model.addAttribute("table01Data", r02.findByIdGreaterThan(id));
return "01/list01";
}
@RequestMapping("13") // mailAddressがnullのデータを検索
public String findByMailAddressIsNull(Model model) {
model.addAttribute("table01Data", r02.findByMailAddressIsNull());
return "01/list01";
}
@RequestMapping("14") // mailAddressがnullではないデータを検索
public String findByMailAddressNotNull(Model model) {
model.addAttribute("table01Data", r02.findByMailAddressNotNull());
return "01/list01";
}
@RequestMapping("15/{id1}/{id2}") // idがid1~id2の範囲のデータを取得し、id昇順で並べ替え
public String findByIdBetweenOrderByIdAsc(Model model, @PathVariable Integer id1, @PathVariable Integer id2) {
model.addAttribute("table01Data", r02.findByIdBetweenOrderByIdAsc(id1,id2));
return "01/list01";
}
@RequestMapping("16/{id1}/{id2}") // idがid1~id2の範囲のデータを取得し、id降順で並べ替え
public String findByIdBetweenOrderByIdDesc(Model model, @PathVariable Integer id1, @PathVariable Integer id2) {
model.addAttribute("table01Data", r02.findByIdBetweenOrderByIdDesc(id1,id2));
return "01/list01";
}
@RequestMapping("18/{id1}/{id2}/{id3}") // idがid1,id2,id3のいずれかであるデータを検索(in (id1,id2,id3) になる)
public String findByIdIn(Model model, @PathVariable Integer id1, @PathVariable Integer id2, @PathVariable Integer id3) {
List<Integer> idList = new ArrayList<>();
idList.add(id1);
idList.add(id2);
idList.add(id3);
model.addAttribute("table01Data", r02.findByIdIn(idList));
return "01/list01";
}
@RequestMapping("19/{id1}/{id2}/{id3}") // idがid1,id2,id3のいずれでもないデータを検索(not in (id1,id2,id3) になる)
public String findByIdNotIn(Model model, @PathVariable Integer id1, @PathVariable Integer id2, @PathVariable Integer id3) {
List<Integer> idList = new ArrayList<>();
idList.add(id1);
idList.add(id2);
idList.add(id3);
model.addAttribute("table01Data", r02.findByIdNotIn(idList));
return "01/list01";
}
@RequestMapping("20/{str}") // firstNameにstrが含まれるデータを検索。like %str%の形にする
// firstName like str になるのだが、前後に%をつけないといけないので、like %str%にするならContainsのほうが簡単。前方一致・後方一致に使うべきだろう
public String findByFirstNameLike1(Model model, @PathVariable String str) {
str = "%" + str + "%";
model.addAttribute("table01Data", r02.findByFirstNameLike(str));
return "01/list01";
}
@RequestMapping("21/{str}") // firstNameにstrが含まれるデータを検索。前方一致
public String findByFirstNameLike2(Model model, @PathVariable String str) {
str = str + "%";
model.addAttribute("table01Data", r02.findByFirstNameLike(str));
return "01/list01";
}
@RequestMapping("22/{str}") // firstNameにstrが含まれるデータを検索。後方一致
public String findByFirstNameLike3(Model model, @PathVariable String str) {
str = "%" + str;
model.addAttribute("table01Data", r02.findByFirstNameLike(str));
return "01/list01";
}
@RequestMapping("23") // 総デー多数を取得する
public String dataCount(Model model) {
model.addAttribute("dataCount", r02.count());
// R02 リポジトリに結びついているTable01の総データ数を取得
return "other/dataCount";
}
@RequestMapping("24/{id}") // 指定のidのデータが存在するかを調べる
public String dataExists(Model model, @PathVariable Integer id) {
Table01 table01 = new Table01();
table01.setId(id); // 検索条件のidを設定
Example<Table01> example = Example.of(table01);
// Exampleは検索条件を設定するクラス?なのかな
model.addAttribute("result", r02.exists(example));
// 設定したidのデータが存在するかを取得する。戻り値はboolean
// ※リポジトリのインターフェイスにはexists()は無くても動作する
return "other/result01"; // 結果を表示するページへ
}
@RequestMapping("25") // Sexがmaleのデータの数を取得
public String maleDataCount(Model model) {
Table01 table01 = new Table01();
table01.setSex(Sex.male); // 検索条件のsexを設定
Example<Table01> example = Example.of(table01);
model.addAttribute("result", r02.count(example));
// データ数を取得する
return "other/result01"; // 結果を表示するページへ
}
@RequestMapping("26") // Sexがmaleのデータを全取得
public String maleData(Model model) {
Table01 table01 = new Table01();
table01.setSex(Sex.male); // 検索条件のsexを設定
Example<Table01> example = Example.of(table01);
model.addAttribute("table01Data", r02.findAll(example));
// 検索条件に合うデータを全取得
return "01/list01"; // 結果を表示するページへ
}
@RequestMapping("27") // Sexがmaleで、idが5のデータを全取得
public String maleAnd5Data(Model model) {
Table01 table01 = new Table01();
table01.setSex(Sex.male); // 検索条件のsexを設定
table01.setId(5); // 2番目の条件も設定できる
Example<Table01> example = Example.of(table01);
model.addAttribute("table01Data", r02.findAll(example));
return "01/list01"; // 結果を表示するページへ
}
@RequestMapping("28") // birthday昇順でソートする
public String sort1(Model model) {
model.addAttribute("table01Data", r02.findAll(new Sort("birthday")));
// birthday昇順でソート
return "01/list01"; // 結果を表示するページへ
}
@RequestMapping("29") // id降順でソートする
public String sort2(Model model) {
model.addAttribute("table01Data", r02.findAll(new Sort(Sort.Direction.DESC,("id"))));
// id降順でソート
return "01/list01"; // 結果を表示するページへ
}
// ※ソートの条件指定はもっと複雑にできるので、詳しくは調べて
@RequestMapping("30") // データがDBに反映されるタイミング
@Transactional(readOnly=false)
public String updateTiming(Model model) {
List<Table01> list = r02.findAll();
list.get(0).setFirstName("ZZZ"); // Entiryの値を変更しただけでは、DBへは反映されない
r02.findAll(); // テーブルにアクセスするので、この時点でupdateが実行され、DBへ反映される
list.get(0).setLastName("XXX");
r02.flush(); // 明示的にupdateを実行。DBへ反映される
list.get(0).setFirstName("YYY"); // DBへ反映されていない変更は、トランザクションの終了時にDBへ反映される
return "01/list01"; // 結果を表示するページへ
//ということを本には書いてあるけど、実際にはトランザクションを実行するまではDBには反映されていないみたい。
//ただ信頼できそうなサイトでも同じ事を書いてあるので、実際は反映されているのかも
}
@RequestMapping("31") // データの更新と挿入
@Transactional(readOnly=false)
public String updateAndInsert(Model model) {
Table01 table01 = new Table01();
table01.setId(10); // 存在するデータのidを指定
table01.setFirstName("PPP");
table01.setLastName("lll");
r02.save(table01); // Entityの変更を保存。DBへの反映はまだされない。既存のデータなので更新になる
Table01 table01_2 = new Table01();
table01_2.setId(20); // 存在しないデータのidを指定
table01_2.setFirstName("EEE");
table01_2.setLastName("eee");
table01_2 = r02.saveAndFlush(table01_2);
// Entityの変更を保存し、即座にDBに反映。既存のデータではないので挿入になる。saveでも同じ役割になる(DB反映はされないが)
model.addAttribute("table01Data", table01_2);
return "01/list01"; // 結果を表示するページへ
}
@RequestMapping("32") // データの削除
@Transactional(readOnly=false)
public String delete(Model model) {
Table01 table01 = new Table01();
table01.setId(10); // 存在するデータのidを指定
r02.delete(table01); // データを削除
Table01 table01_2 = new Table01();
table01_2.setId(30); // 存在しないデータのidを指定
table01_2.setFirstName("EEE");
// 存在しないidのEntityでも、Not Nullのフィールドは値を設定しないとエラーになる
table01_2.setLastName("eee");
r02.delete(table01_2);
// 存在しないデータを削除しても、エラーにはならないが意味は無い
Table01 table01_3 = new Table01();
Table01 table01_4 = new Table01();
Table01 table01_5 = new Table01();
table01_3.setId(2); // 存在するデータのidを指定
table01_4.setId(3); // 存在するデータのidを指定
table01_5.setId(4); // 存在するデータのidを指定
List<Table01> list = new ArrayList<>();
list.add(table01_3);
list.add(table01_4);
list.add(table01_5);
r02.deleteInBatch(list); // listのEntityを全て削除する
r02.deleteAll(); // 全データを削除する
r02.deleteAllInBatch(); // 全データを削除する
// ※ "InBatch" が付くメソッドは、1つのクエリーですべての処理を実行するので、多数のEntityを処理する場合は効率がいい
// "InBatch" が付かないメソッドは、Entityごとにクエリを発行するので処理が遅くなることに注意
return "01/list01";
}
}
package p1.restControllers;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.MediaType;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController // 文字列等のデータ、JsonやXML等を返すWebAPI用のコントローラとして使う
public class RestController01 {
@RequestMapping("rest01")
public String aaa() {
return "rest01にアクセスがありました";
// http://localhost:8090/rest01 にアクセスすれば、"rest01にアクセスがありました"と表示される
}
@RequestMapping("rest02")
public void bbb(HttpServletResponse res) throws IOException {
// HttpServletResponseで、指定のhtmlファイルの内容をhtml形式で出力する。RestControllerはこのような使い方が多いか
File file = new File("src/main/resources/files/aaa.html");
res.setContentLength((int) file.length());
res.setContentType(MediaType.TEXT_HTML_VALUE);
// MediaType.TEXT_HTML_VALUE で、HTML形式を指定。他にもファイルタイプを指定する定数がたくさんある
FileCopyUtils.copy(new FileInputStream(file), res.getOutputStream());
// aaa.htmlの内容をコピーして、レスポンスとして出力する。結果としてaaa.htmlをViewとして表示させたのと同じことになる
}
}
package p1.controller;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import p1.repository.ProductMasterRepository;
import p1.repository.SalesDataRepository;
import p1.repository.StaffMasterRepository;
import p1.repository.WorkingDataRepository;
import p1.repository.entity.Product_master;
import p1.repository.entity.Sales_data;
import p1.repository.entity.Staff_master;
import p1.repository.entity.Working_data;
@Controller
@RequestMapping("hsystem")
public class ControllerH {
@Autowired
private StaffMasterRepository staffMasterRepository;
@Autowired
private SalesDataRepository salesDataRepository;
@Autowired
private WorkingDataRepository workingDataRepository;
@Autowired
private ProductMasterRepository productMasterRepository;
@RequestMapping("01/{id}")
public String getById(Model model, @PathVariable Integer id) {
Optional<Staff_master> data = staffMasterRepository.findById(id);
if(!data.equals(Optional.empty())) {
model.addAttribute("staffMasterData", data.get());
return "hsystem/staffMasterList";
}else {
return "error/error01";
}
}
@RequestMapping("02/{id}")
public String getById2(Model model, @PathVariable Integer id) {
Optional<Sales_data> data = salesDataRepository.findById(id);
if(!data.equals(Optional.empty())) {
model.addAttribute("salesDataData", data.get());
return "hsystem/salesDataList";
}else {
return "error/error01";
}
}
@RequestMapping("03/{id}")
public String getById3(Model model, @PathVariable Integer id) {
Optional<Working_data> data = workingDataRepository.findById(id);
if(!data.equals(Optional.empty())) {
model.addAttribute("workingDataData", data.get());
return "hsystem/workingDataList";
}else {
return "error/error01";
}
}
@RequestMapping("04/{id}")
public String getById4(Model model, @PathVariable Integer id) {
Optional<Product_master> data = productMasterRepository.findById(id);
if(!data.equals(Optional.empty())) {
model.addAttribute("productMasterData", data.get());
return "hsystem/productMasterList";
}else {
return "error/error01";
}
}
@RequestMapping("05/{id}")
public String greaterId(Model model, @PathVariable Integer id) {
List<Sales_data> list = salesDataRepository.greaterId(id);
model.addAttribute("salesDataData", list);
return "hsystem/salesDataList";
}
@RequestMapping("06/{id1}/{id2}")
public String betweenId(Model model, @PathVariable Integer id1, @PathVariable Integer id2) {
List<Sales_data> list = salesDataRepository.betweenId(id1,id2);
model.addAttribute("salesDataData", list);
return "hsystem/salesDataList";
}
@RequestMapping("07/{id1}/{id2}")
@Transactional(readOnly=false)
public String deleteBetweenId(Model model, @PathVariable Integer id1, @PathVariable Integer id2) {
int resultInt = salesDataRepository.deleteBetweenId(id1,id2);
System.out.println(resultInt);
List<Sales_data> list = salesDataRepository.findAll();
model.addAttribute("salesDataData", list);
return "hsystem/salesDataList";
}
}
package p1.repository;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import p1.repository.entity.Table01;
@Repository
public interface R02 extends JpaRepository<Table01, Integer> {
public Optional<Table01> findById(Integer id);
public List<Table01> findAllById(List<Integer> idList); // 複数のidを指定してデータを取得
// findAllById(List<Integer>) は、Postgresではエラーになってしまうらしい
public List<Table01> findByIdBetween(Integer id1, Integer id2); // idがid1~id2の範囲のデータを取得
public List<Table01> findByFirstName(String firstName); // firstNameで検索(完全一致)
public List<Table01> findByFirstNameContains(String str); // firstNameにstrが含まれるデータを検索(firstName like %str% になる)
public List<Table01> findByFirstNameNotContains(String str); // firstNameにstrが含まれないデータを検索(firstName not like %str% になる)
public List<Table01> findByFirstNameStartsWith(String str); // firstNameがstrで始まるデータを検索(firstName like str% になる)
public List<Table01> findByFirstNameEndsWith(String str); // firstNameがstrで終わるデータを検索(firstName like %str になる)
public List<Table01> findByIdAndFirstName(Integer id,String firstName); // idとfirstNameのAND条件で検索
public List<Table01> findByIdOrFirstName(Integer id,String firstName); // idとfirstNameのOR条件で検索
public List<Table01> findByIdLessThan(Integer id); // idが~未満の条件で検索
public List<Table01> findByIdGreaterThan(Integer id); // idが~より大きいの条件で検索
public List<Table01> findByMailAddressIsNull(); // mailAddressがnullのデータを検索
public List<Table01> findByMailAddressNotNull(); // mailAddressがnullではないデータを検索
public List<Table01> findByIdBetweenOrderByIdAsc(Integer id1, Integer id2); // idがid1~id2の範囲のデータを取得し、id昇順で並べ替え
public List<Table01> findByIdBetweenOrderByIdDesc(Integer id1, Integer id2); // idがid1~id2の範囲のデータを取得し、id降順で並べ替え
public List<Table01> findByIdIn(List<Integer> idList); // idがidListのいずれかであるデータを検索(in (id1,id2,id3) になる)
public List<Table01> findByIdNotIn(List<Integer> idList); // idがidListのいずれでもないデータを検索(not in (id1,id2,id3) になる)
public List<Table01> findByFirstNameLike(String str);
// firstNameにstrが含まれるデータを検索(firstName like str になるのだが、前後に%をつけないといけないので、Contains,StartsWith,EndsWithのほうが簡単
}
package p1.repository;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import p1.repository.entity.Sales_data;
public interface SalesDataRepository extends JpaRepository<Sales_data, Integer> {
public Optional<Sales_data> findById(Integer id);
@Query("SELECT s FROM Sales_data s WHERE s.id > :id")
public List<Sales_data> greaterId(@Param("id")Integer id);
@Query("SELECT s FROM Sales_data s WHERE s.id BETWEEN :id1 AND :id2")
public List<Sales_data> betweenId(@Param("id1")Integer id1, @Param("id2")Integer id2);
@Query("DELETE FROM Sales_data s WHERE s.id BETWEEN :id1 AND :id2")
@Modifying // 更新・削除の場合は@Modifyingが必要
public int deleteBetweenId(@Param("id1")Integer id1, @Param("id2")Integer id2);
}