Spring 08
public List<T> getAll();
エンティティを取得します。
public T findById(long id);
ID番号を引数に指定してエンティティを検索し、返します。
public List<T> findByName(String name);
名前からエンティティを検索します。
getSingleResult()
1つの結果しか検索されません。
Query(Interface)
選択したクエリーを実行して、結果を戻ります。
entityManager.createQuery
基準のクエリを実行するために、TypedQueryのインスタンスを作成します。
Long.parseLong
Stringの型がLongに変更します。
Spring 07
・useridの保存機能を修正しました。
問題点:UserEntityが値をもらえません。
解決方法:Controllerで値をもらって、保存します。
public ModelAndView form(
@ModelAttribute("formModel") @RequestParam(value = "userid", required = true) String userid,
UserEntity user, ModelAndView mav) {
user.setUserId(userid);
repository.saveAndFlush(user);
return mav;
}
Controllerで値をもらうのは、Controllerの役割じゃないと思います。
他の解決方法がないので、Controllerで値をもらいます。
・エラーメッセージを出力しました。
<li th:each="error : ${#fields.detailedErrors()}"
class="err" th:text="${error.message}" />
#fields
エンティティの各フィールドをバリデーションチェックした結果などがまとめられたオブジェクトです。
detailedErrors
発生したエラーに関する情報をひとまとめのリストとして返すメソッドです。
・各入力フィールドにエラーを表示
<input type="text" name="name" th:value="*{name}" th:errorclass="err" />
エラーが発生した際に適用されるクラス名を指定します。
エラーが起きたらテキストを赤い表示に変えます。
<div th:if="${#fields.hasErrors('name')}" th:errors="*{name}" th:errorclass="err">
エラーが発生している時だけ表示します。
このフィールドのエラーだけを表示します。
・エラーメッセージの日本語化
新しいプロパティファイルを追加しました。
org.hibernate.validator.constraints.NotBlank.message = 空白は不可です。
org.hibernate.validator.constraints.NotEmpty.message = 空白は不可です。
javax.validation.constraints.Max.message = {value} より小さくして下さい。
javax.validation.constraints.Min.message = {value} より大きくして下さい。
org.hibernate.validator.constraints.Email.message = メールアドレスではありません。
・オリジナルのバリデータを作成しました。
下記のクラスは入力したデータ型を確認する機能です。
public class PhoneValidator implements ConstraintValidator<Phone, String> {
@Override
public void initialize(Phone phone) {
}
@Override
public boolean isValid(String input, ConstraintValidatorContext cxt) {
if (input == null) {
return false;
}
return input.matches("[0-9()-]*");
}
}
下記のインターフェースは新しいアノテーションを使えるようになるものです。
@Documented
@Constraint(validatedBy = PhoneValidator.class)
@Target({ ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@ReportAsSingleViolation
public @interface Phone {
String message() default "please input a phone number.";
Class<?> groups() default {};
Class<? extends Payload> payload() default {};
}
補充:
インターフェースとは、クラスに含まれるメソッドの具体的な処理内容を記述せず、変数とメソッドの型のみを定義したものです。
抽象メソッドは具体的な処理内容を記述せず、メソッド名や引数などの定義だけを宣言するメソッドです。
・Serializable(シリアライズ・直列化)
この機能を使うと、簡単にインスタンスを外部記憶装置などに保存し、インスタンスの情報を永続化することができます。
・@Controller、@Service、@Repository、@Componentの違い
@Controller
Spring MVCでコントローラー層のクラスに付与します。
Controller は、主に以下の役割を担います。
1.画面遷移の制御
2.ドメイン層の Service の呼出 (主処理を実行します。)
@Service
Sping MVCでサービス層のクラス(ビジネスロジック等)に付与します。
Service は業務処理を提供します。
@Repository
Spring MVCでデータ層のクラス(DAO等のDBアクセスを行うクラス)に付与します。
@Component
Spring MVCに限らず、SpringのDIコンテナにbeanとして登録したいクラスへ付与します。
@SuppressWarning
コンパイル・ユニットのサブセットに関するコンパイル警告を無効にできます。
@SuppressWarnings("unchecked")
unchecked : 未検査のオペレーションに関連する警告の抑止
@PersistenceContext
EntityManagerのbeanを取得してフィールドに設定します。
Spring 06
・Thymeleaf
エスケープ処理機能が内蔵しています。
(Controller)
@RequestMapping("/")
public ModelAndView index(ModelAndView mav) {
mav.setViewName("index");
mav.addObject("msg","message 1<hr/>message 2<br/>message 3");
return mav;
}
(index)
<body>
<h1 th:text="#{content.title}">Helo page</h1>
<p th:text="${msg}">message.</p>
</body>
使いたくない場合は、utextに変わります。
<body>
<h1 th:text="#{content.title}">Helo page</h1>
<p th:utext="${msg}">message.</p>
</body>
・GenerationType
問題点:AUTOで生成することができません。
解決方法:IDENTITYに変更しました。
@GeneratedValue(strategy = GenerationType.AUTO)
データベースごとに異なる方法を選択し,主キー値を生成します。
@GeneratedValue(strategy = GenerationType.IDENTITY)
テーブルのidentity列を利用して,主キー値を生成します。
(ブラウザのエラー)
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Tue May 28 14:03:31 JST 2019
There was an unexpected error (type=Internal Server Error, status=500).
error performing isolated work; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: error performing isolated work
(Consoleのエラー)
Hibernate: select mydata0_.id as id1_0_, mydata0_.age as age2_0_, mydata0_.mail as mail3_0_, mydata0_.memo as memo4_0_, mydata0_.name as name5_0_ from mydata mydata0_
Hibernate: select next_val as id_val from hibernate_sequence for update
2019-05-28 14:03:31.119 ERROR 1364 --- [nio-8080-exec-3] o.hibernate.id.enhanced.TableStructure : could not read a hi value
java.sql.SQLSyntaxErrorException: Table 'test_01.hibernate_sequence' doesn't exist
@PostConstruct
データの初期化処理
保存したデータは、アプリケーションを終了し、再度起動すると消えてしまっています。
問題点:初期化が成功しましたが、終了の時、データが残っています。
解決方法:IDを指定して、データを初期化処理します。
@PostConstruct
public void init(){
MyData d1 = new MyData();
d1.setId(1);
d1.setName("tuyano");
d1.setAge(123);
d1.setMail("syoda@tuyano.com");
d1.setMemo("this is my data!");
repository.saveAndFlush(d1);
}
この解決方法はよくないと思います。
DatabaseにIDは1のデータがいないなら、新しいデータを作成しまいました。
そして、データを削除するのはいけません。削除したら、上記の状況が発生します。
Columnにunique keyを追加する場合は、重複のデータを作成すると、バグになってしまいます。
・Optional
nullかもしれないオブジェクトをラップするためのクラス。
Spring 05
・JpaRepository
databaseの操作というクラスです。
CrudRepositoryは、CRUD機能を提供しています。
PagingAndSortingRepositoryは、ページングおよびソートレコードを行うためのメソッドを提供しています。
JpaRepositoryは、永続コンテキストの更新やレコードの一括削除など、JPA関連のメソッドを提供しています。
@Autowired
userRepositoryというBeanを取得することです。
Springによって自動生成されます。
データを処理するために使用します。
・Thymeleaf属性
th:value th:value="${msg}"
th:object th:object="${loginBean}"
th:field th:field="*{username}"
@readOnly
boolean読み取り専用かどうかを指定する。デフォルトはfalse。
・Interable
もらった配列の文字
com.example.demo.entity.UserEntity@2d0716be
問題点:配列が表示されませんでした。
<th:each="obj : ${data}">
<th:text="${obj}"> <----使えます。
<th:text="${obj.userid}"> <----使えません。
解決方法:privateがpublicに変更します。
(UserEntity)
以前
@Column(name = "t_user")
private String userid;
現在
@Column(name = "t_user")
public String userid;
Spring 04
・Buttonで画面の遷移
@Controller
public class NewController {
@RequestMapping("/")
public ModelAndView index (ModelAndView mav){
mav.setViewName("index");
return mav;
}
@RequestMapping("/other")
public String other (){
return "redirect:/";
}
@RequestMapping("/new")
public String user(){
return "forward:/";
}
}
redirect:/
localhost:8080/otherに遷移したら、localhost:8080/に転送します。
forward:/
localhost:8080/newに遷移します。
<form method="post" action="result">
actionで指定のページへ遷移します。
・POSTでボタンを押すと、データを保存します。
@RequestMapping(value = { "/result" }, method = { RequestMethod.POST })
public ModelAndView postTest3() {
ModelAndView mv = new ModelAndView();
mv.setViewName("result");
return mv;
}
結果を保存したら、成功メッセージが表示されるページに遷移します。
@RequestMapping(value = "/result",method = RequestMethod.POST)
public UserEntity create(UserEntity entity)
{
return userJPA.save(entity);
}
データを保存することです。
結果:passwordの保存は成功したが、user_idの保存は失敗しました。
原因:まだわかりません。
URLで実行したら、機能は正常です。しかし、POSTで実行するのはうまくできません。
・あった状況
POSTとGET同じURLに移動して、違う結果をもらいます。(値をもらう問題だと思います。)
POSTはエラーページに遷移します。
GETは正常な画面に遷移します。
POSTで新しい画面に遷移して、GETと同じ画面に遷移します。(上記と矛盾しているんですが、実際に発生しまいました。)
ChromeとEdgeは配列が表示しますが、Eclipseのブラウザはダウンロードの画面が表示されます。
JSONのファイルはChromeとEdgeに表示することができると思います。ですから、この結果をもらいました。
GETとPOSTの使い方は違うので、同じ移動方法を使わないほうがいいと思います。
@RestController
@RequestMapping(value = "/user")
public class UserController {
@Autowired
private UserJPA userJPA;
@RequestMapping(value ="/list" ,method = RequestMethod.GET)
public List<UserEntity> list(){
return userJPA.findAll();
}
@RequestMapping(value = { "/result" }, method = { RequestMethod.POST })
public ModelAndView postTest3() {
ModelAndView mv = new ModelAndView();
mv.setViewName("result");
return mv;
}
}
赤い部分は、localhost:8080/user/listに遷移したら、DataBaseのデータが表示されます。
<form method="post" action="user/result">
青い部分は、POSTで値を渡して、GETの部分を実行できます。
これから、POSTとGETの機能を分別します。しないと、混乱するかもしれません。
Spring 03
使う前に、Spring Boot CLIを用意します。
ファイルの拡張子はgroovyです。
実行方法:コマンドプロンプトを起動して、Desktopに遷移して、spring run XXX.groovyを入力します。
app.groovy
@RestController
class App{
@RequestMapping("/")
def home(){
"Hello!!"
}
}
起動したら、Webブラウザでhttp://localhost:8080/にアクセスします。
画面に「Hello!!」とテキストが表示されます。
流れ:Webブラウザ -> サーバー -> コントローラー -> メソッド -> 返値 -> Webブラウザ
Thymeleaf
Java XML、 XHTML、 HTML5 のテンプレートエンジンです。Thymeleafの目標はJSPを完全に取って代わることです。
文字化け解決方法
native2ascii -encoding utf-8 app.groovy app2.groovy
MavenとGradle
プロジェクト自動構築ツールです。MavenはXMLで配置します。
GradleはGroovyで配置します。
流れ:
1.ソースコードをコンパイルします。
2.単体テストと統合テストを実行します。
3.スタティックコードを分析して、分析結果を生成します。
4.リリースバージョンを作ります。
5.ターゲット環境にデプロイします。
6.配信プロセスをデプロイします。
7.スモークテストおよび自動機能テストを実施します。
Maven
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
Gradle
dependencies {
compile(‘org.springframework:spring-core:2.5.6’)
compile(‘org.springframework:spring-beans:2.5.6’)
}
上記通り、MavenよりGradleのコードは短いです。しかし、今よく使うはMavenです。そして、Mavenの利点もあります。また、MavenとGradleが同時に存在することができます。
Githubに優秀なオープンソースは二つ依存性の注入方法が提供されています。
指定のhtmlに遷移します。
mv.setViewName("html名");
POST用のパラメータを受け取る
@RequestMapping(value = {"/formPost"}, method = {RequestMethod.POST})
GET用のパラメータを受け取る
@RequestMapping(value = {"/formPost"}, method = {RequestMethod.GET})
値の保存
mv.addObject("name", name);
Spring 02
・JSPとSpring Boot
JSP maven
<!-- spring boot tomcat jsp-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
Servlet maven
<!--servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
JSTL maven
<!-- jstl-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
・JSPを利用するために、JSPのフォルダーを指定します。
application.properties
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
下記のは、もし/indexへ遷移したら、springmvcがJSPのフォルダーのindex.jspを探します。
@Controller
public class IndexController {
@RequestMapping(value = "/index",method = RequestMethod.GET)
public String index(){
return "index";
}
}
@Controller
使用者からもらったURLを対応のサービスに渡します。よくRequestMappingと一緒に使われています。
@RequestMapping
ルーティング情報を提供します。
・SpringBootがSpringDataJPAでCRUDを作ります。
<!--mysql-connector-java-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- spring data jpa -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--tomcat-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<!--<scope>provided</scope>-->
</dependency>
内部のtomcatで実行する場合は、scopeを削除します。
@ResponseBody
戻り値をHTTP response bodyに書き込みます。
@RestController
JsonやXML等を返すWebAPI用のコントローラで使用します。
・DataBaseの接続とJPA(Java Persistence API )
下記の二つは同じ機能ですが、一つのコードは長いです。もう一つは短くて、理解やすいです。しかし、yaml形式の定義ファイルはpropertiesのルールより厳しいです。一つスペースも影響されています。
(application.properties)
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=matt
spring.datasource.password=12345
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
(application.yml)
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: matt
password: 12345
driver-class-name: com.mysql.cj.jdbc.Driver
Hibernate
Java のためのORM(Object-Relational Mapping) ライブラリであり、オブジェクト指向のドメインモデルを関係データベースにマッピングするためのフレームワークを提供します。
@Entity
テーブルを指定します。
@Table
よく@Entityと一緒に使われています。
@id
一つテーブルは一つprimary keyしかありません。
@GeneratedValue
primary key生成方法です。AUTO、INDENTITY、SEQUENCEとTABLE 四つ方法があります。既定値はAUTOです。
@Column
特定のデータを指定します。特定の属性を指定することができます。今回は使用しません。
@Autowired
Beanから自動的に導入します。
JpaRepository
SpringDataJPAが提供した簡単なデータ操作インターフェースです
JpaSpecificationExecutor
SpringDataJPAが提供した複雑な検査インターフェースです。
Serializable
直列化インターフェースです。
・DataBaseの接続問題
原因:mysql-connector-java の5.1.33 ~ 37 のバグでした。
詳しいページ:https://www.nakamuri.info/mw/index.php/Mysql-connector-java_%E3%81%AE%E3%83%90%E3%82%B0%E3%81%A7_Java%E3%81%8B%E3%82%89MySQL%E3%81%AB%E6%8E%A5%E7%B6%9A%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84
以前
url: jdbc:mysql://localhost:3306/test_01?characterEncoding=utf8
現在
url: jdbc:mysql://localhost:3306/test_01?characterEncoding=UTF-8&serverTimezone=JST
・CRUDを作成しました。
バグ:Create機能は実行できません。
原因:sequenceでprimary keyを生成するのは、MySQLに対してサポートしません。MySQLはidentityを使っています。
解決方法:@GeneratedValue(strategy = javax.persistence.GenerationType.IDENTITY)