[SpringBoot2.4.3] JPA

エンティティクラスの作成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package com.example.demo;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
 
@Entity
@Table(name="mydata")
public class MyData{
     
    @Id
    @GeneratedValue(strategry = GenerationType.AUTO)
    @Column
    private long id;
     
    @Column(length = 50, nullable = false)
    private String name;
     
    @Column(length = 200, nullable = true)
    private String mail;
     
    @Column(nullable = true)
    private Integer age;
     
    @Column(nullable = true)
    private String memo;
     
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getMail() {
        return mail;
    }
    public void setMail(String mail) {
        this.mail = mail;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public String getMemo() {
        return memo;
    }
    public void setMemo(String memo) {
        this.memo = memo;
    }
}

@Entity
エンティティクラスを示すアノテーション
@Table(name=”mydata”)
割り当てられるテーブルを指定
@Id
プライマリーキー
@GeneratedValue(strategry = GenerationType.AUTO)
プライマリーキーのフィールドに対し値を自動生成
@Column
カラム

Repository

1
2
3
4
5
6
7
8
9
10
package com.example.demo.repositories;
 
import com.example.demo.MyData;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
 
@Repository
public interface MyDataRepository extends JpaRepository<MyData, Long> {
     
}

controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
 
import com.example.demo.repositories.MyDataRepository;
 
@Controller
public class HelloController {
     
    @Autowired
    MyDataRepository repository;
     
    @RequestMapping("/")
    public ModelAndView index(ModelAndView mav) {
        mav.setViewName("index");
        mav.addObject("msg","this is sample content.");
        Iterable<MyData> list = repository.findAll();
        mav.addObject("data", list);
        return mav;
    }
}

html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<table>
    <form method="post" action="/" th:object="${formModel}">
    <tr>
        <td><label for="name">名前</label></td>
        <td><input type="text" name="name" th:value="*{name}"></td>
    </tr>
    <tr>
        <td><label for="age">年齢</label></td>
        <td><input type="text" name="age" th:value="*{age}"></td>
    </tr>
    <tr>
        <td><label for="mail">メール</label></td>
        <td><input type="text" name="mail" th:value="*{mail}"></td>
    </tr>
    <tr>
        <td><label for="memo">メモ</label></td>
        <td><textarea name="memo" th:text="*{memo}" cols="20" rows="5"></textarea></td>
    </tr>
    <tr>
        <td></td>
        <td><input type="sbmit"></td>
    </tr>
    </form>
</table>
<hr>
<table>
    <tr><th>ID</th><th>名前</th></tr>
    <tr th:each="obj : ${datalist}">
        <td th:text="${obj.id}"></td>
        <td th:text="${obj.name}"></td>
    </tr>
</table>

Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
 
import com.example.demo.repositories.MyDataRepository;
 
@Controller
public class HelloController {
     
    @Autowired
    MyDataRepository repository;
     
    @RequestMapping(value="/", method=RequestMethod.GET)
    public ModelAndView index(
            @ModelAttribute("formModel") MyData mydata,
            ModelAndView mav) {
        mav.setViewName("index");
        mav.addObject("msg","this is sample content.");
        Iterable<MyData> list = repository.findAll();
        mav.addObject("datalist", list);
        return mav;
    }
     
    @RequestMapping(value="/", method= RequestMethod.POST)
    @Transactional(readOnly=false)
    public ModelAndView form(
            @ModelAttribute("formModel") MyData mydata,
            ModelAndView mav) {
        repository.saveAndFlush(mydata);
        return new ModelAndView("redirect:/");
    }
}

なんやこれは。。。
HSQLDB/H2 はデフォルトでメモリ内にデータをキャッシュしている。

[SpringBoot2.4.3] Thymeleafインライン・レイアウト2

### th:each
controller

1
2
3
4
5
6
7
8
9
10
@RequestMapping("/{month}")
public ModelAndView index(ModelAndView mav) {
    mav.setViewName("index");
    ArrayList<String[]> data = new ArrayList<String[]>();
    data.add(new String[] {"taro","taro@yamada","090-999-999"});
    data.add(new String[] {"hanako","hanako@sato","080-888-888"});
    data.add(new String[] {"sachiko","sachiko@saito","080-888-888"});
    mav.addObject("data",data);
    return mav;
}
1
2
3
4
5
6
7
8
9
10
11
12
<table>
    <tr>
        <th>NAME</th>
        <th>MAIL</th>
        <th>TEL</th>
    </tr>
    <tr th:each="obj:${data}">
        <td th:text="${obj[0]}"></td>
        <td th:text="${obj[1]}"></td>
        <td th:text="${obj[2]}"></td>
    </tr>
</table>

### プリプロセッシング
-> 式の一部を事前に評価させ、その結果を元に変数式を実行する
概念がイマイチよくわからんが。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@RequestMapping("/{num}")
public ModelAndView index(@PathVariable int num, ModelAndView mav) {
    mav.setViewName("index");
    mav.addObject("num",num);
    if (num > 0) {
        mav.addObject("check","num >= data.size() ? 0 : num");
    } else {
        mav.addObject("check", "num <= data.size() * -1 ? 0 : num * -1");
    }
    ArrayList<DataObject> data = new ArrayList<DataObject>();
    data.add(new DataObject(0, "taro","taro@yamada"));
    data.add(new DataObject(1, "hanako","hanako@sato"));
    data.add(new DataObject(2, "sachiko","sachiko@saito"));
    mav.addObject("data",data);
    return mav;
}

html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<p th:text="|expression[ ${check} ]|"></p>
<table th:object="${data.get(__${check}__)}">
    <tr>
        <th>ID</th>
        <td th:text="*{id}"></td>
    </tr>
    <tr>
        <th>NAME</th>
        <td th:text="*{name}"></td>
    </tr>
    <tr>
        <th>MAIL</th>
        <td th:text="*{value}"></td>
    </tr>
</table>


ん? 意味がわからん。

### インライン処理
th:inline=”text”と書くと、そのタグの内部のみインライン処理が可能になる

1
2
3
4
5
6
7
8
9
10
@RequestMapping("/")
public ModelAndView index(ModelAndView mav) {
    mav.setViewName("index");
    ArrayList<DataObject> data = new ArrayList<DataObject>();
    data.add(new DataObject(0, "taro","taro@yamada"));
    data.add(new DataObject(1, "hanako","hanako@sato"));
    data.add(new DataObject(2, "sachiko","sachiko@saito"));
    mav.addObject("data",data);
    return mav;
}

html

1
2
3
4
5
6
7
8
9
10
11
12
<table th:inline="text">
    <tr>
        <th>ID</th>
        <th>NAME</th>
        <th>MAIL</th>
    </tr>
    <tr th:each="obj: ${data}">
        <td>[[${obj.id}]]</td>
        <td>[[${obj.name}]]</td>
        <td>[[${obj.value}]]</td>
    </tr>
</table>

#### jsのインライン処理

1
2
3
4
5
6
@RequestMapping("/{tax}")
public ModelAndView index(@PathVariable int tax, ModelAndView mav) {
    mav.setViewName("index");
    mav.addObject("tax",tax);
    return mav;
}
1
2
3
4
5
6
7
8
9
10
11
<h1>Helo page</h1>
<p id="msg"></p>
<input type="text" id="text1">
<button onclick="action()">click</button>
<script th:inline="javascript">
function action(){
    var val = document.getElementById("text1").value;
    var res = parseInt(val * ((100 + /*[[${tax}]]*/) /100 ));
    document.getElementById("msg").innerHTML = "include tax: " + res;
}
</script>

js側に渡せるってこと?
よくわからんが凄え。

[SpringBoot2.4.3] Thymeleafインライン・レイアウト1

controller

1
2
3
4
5
6
7
8
9
@RequestMapping("/{id}")
public ModelAndView index(@PathVariable int id, ModelAndView mav) {
    mav.setViewName("index");
    mav.addObject("id", id);
    mav.addObject("check", id % 2 == 0);
    mav.addObject("trueVal", "Even number!");
    mav.addObject("falseVal", "Odd number...");
    return mav;
}
1
<p th:text="${id} + ' is '+ (${check} ? ${trueVal} : ${falseVal})"></p>


thymeleaf側で計算すると不思議な感じするなー

1
2
3
4
5
6
7
8
9
@RequestMapping("/{id}")
public ModelAndView index(@PathVariable int id, ModelAndView mav) {
    mav.setViewName("index");
    mav.addObject("id", id);
    mav.addObject("check", id  >= 0);
    mav.addObject("trueVal", "POSITIVE!");
    mav.addObject("falseVal", "negative...");
    return mav;
}
1
2
<p th:if="${check}" th:text="${id} + ' is ' + ${trueVal}">message.</p>
<p th:unless="${check}" th:text="${id} + ' is ' + ${falseVal}">message.</p>

なんやこれ

1
2
3
4
5
6
7
8
9
@RequestMapping("/{month}")
public ModelAndView index(@PathVariable int month, ModelAndView mav) {
    mav.setViewName("index");
    int m = Math.abs(month) % 12;
    m = m == 0 ? 12 : m;
    mav.addObject("month", m);
    mav.addObject("check", Math.floor(m / 3));
    return mav;
}
1
2
3
4
5
6
7
8
9
<p th:if="${check}" th:text="${id} + ' is ' + ${trueVal}">message.</p>
<div th:switch="${check}">
    <p th:case="0" th:text="|${month} - Winter|"></p>
    <p th:case="1" th:text="|${month} - Spring|"></p>
    <p th:case="2" th:text="|${month} - Summer|"></p>
    <p th:case="3" th:text="|${month} - Autumn|"></p>
    <p th:case="4" th:text="|${month} - Winter|"></p>
    <p th:case="*">...?</p>
</div>

なんやこれは。。。普段きちんとコーディングしているかどうか一発でわかるな。ビビるわ。

[SpringBoot2.4.3] Thymeleaf リンク

1
<p><a th:href="@{'/home/' + ${param.id[0]}}">link</a></p>

ん? なんかうまくいかんけど。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@Controller
public class HelloController {
     
    @RequestMapping("/")
    public ModelAndView index(ModelAndView mav) {
        mav.setViewName("index");
        mav.addObject("msg", "current data.");
        DataObject obj = new DataObject(123, "hanako", "hanako@flower");
        mav.addObject("object",obj);
        return mav;
    }
}
 
class DataObject{
     
    private int id;
    private String name;
    private String value;
      
    public DataObject(int id, String name, String value) {
        super();
        this.id = id;
        this.name = name;
        this.value = value;
    }
      
    public int getId() {return id;}
    public void setId(int id) {this.id = id;}
      
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
      
    public String getValue() {return value;}
    public void setValue(String value) {this.value = value;}
}
1
2
3
4
5
6
7
<h1>Helo page</h1>
<p th:text="${msg}">message.</p>
<table th:object="${object}">
    <tr><th>ID</th><td th:text="*{id}"></td></tr>
    <tr><th>NAME</th><td th:text="*{name}"></td></tr>
    <tr><th>MAIL</th><td th:text="*{value}"></td></tr>
</table>

リテラル置換

1
2
3
<div th:object="${object}">
    <p th:text="|my name is *{name}. mail address is *{value}.|">message.</p>
</div>

http://localhost:8080/
my name is hanako. mail address is hanako@flower.

うおおおお、凄え

### htmlを出力

1
2
3
4
5
6
@RequestMapping("/")
public ModelAndView index(ModelAndView mav) {
    mav.setViewName("index");
    mav.addObject("msg", "message 1<hr/>message 2<hr/>message 3");
    return mav;
}
1
<p th:utext="${msg}">message.</p>

unescape

早くアプリ作りてえな

[SpringBoot2.4.3] Thymeleafを学習する

直書きもできる。

1
2
<h1>Helo page</h1>
<p th:text="${new java.util.Date().toString()}"></p>

util object

1
2
3
<p th:text="${#dates.format(new java.util.Date(),'dd/MMM/yyyy HH:mm')}"></p>
<p th:text="${#numbers.formatInteger(1234,7)}"></p>
<p th:text="${#strings.toUpperCase('welcome to Spring!')}"></p>

28/2月/2021 13:03

0001234

WELCOME TO SPRING!
これはすぐわかるね。

1
<p th:text="'from parameter... id=' + ${param.id[0] +',name=' + param.name[0]}"></p>

http://localhost:8080/home?id=123&name=taro
from parameter… id=123,name=taro

### message
messages.properties

1
2
content.title=message sample page.
content.message=this is sample message from properties

Property or field ‘message’ cannot be found on null
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:213) ~[spring-expression-5.3.4.jar:5.3.4]
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:104) ~[spring-expression-5.3.4.jar:5.3.4]
at org.springframework.expression.spel.ast.PropertyOrFieldReference.access$000(PropertyOrFieldReference.java:51) ~[spring-expression-5.3.4.jar:5.3.4]

ん?
再起動したら行けた

なんかよーわからんなw

[SpringBoot2.4.3] ページ移動(フォワード/リダイレクト)

Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
 
@Controller
public class HelloController {
     
    @RequestMapping("/")
    public ModelAndView index(ModelAndView mav) {
        mav.setViewName("index");
        return mav;
    }
    @RequestMapping("/other")
    public String other() {
        return "redirect:/";
    }
    @RequestMapping("/home")
    public String home() {
        return "forward:/";
    }
}


forwardを使う用途がわからんが、実装方法はわかった。

[SpringBoot2.4.3] フォームコントロール

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<form method="post" action="/">
    <div>
        <input type="checkbox" id="check1" name="check1">
        <label for="check1">チェック</label>
    </div>
    <div>
        <input type="radio" id="radioA" name="radio1" value="male">
        <label for="radioA">男性</label>
    </div>
    <div>
        <input type="radio" id="radioB" name="radio1" value="femail">
        <label for="radioB">女性</label>
    </div>
    <div>
        <select id="select1" name="select1" size="4">
            <option value="Windows">Windows</option>
            <option value="Mac">Mac</option>
            <option value="Linux">Linux</option>
        </select>
    </div>
    <div>
        <select id="select2" name="select2" size="4" multiple="multiple">
            <option value="Android">Android</option>
            <option value="iphone">iPhone</option>
            <option value="Winfone">Windows Phone</option>
        </select>
    </div>
    <input type="submit" value="Click">
</form>

Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import org.springframework.stereotype.Controller;
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.servlet.ModelAndView;
 
@Controller
public class HelloController {
     
    @RequestMapping(value="/", method=RequestMethod.GET)
    public ModelAndView index(ModelAndView mav) {
        mav.setViewName("index");
        mav.addObject("msg", "フォームを送信してください。");
        return mav;
    }
     
    @RequestMapping(value="/", method=RequestMethod.POST)
    public ModelAndView send(
            @RequestParam(value="check1",required=false) boolean check1,
            @RequestParam(value="radio1",required=false) String radio1,
            @RequestParam(value="select1",required=false) String select1,
            @RequestParam(value="select2",required=false) String[] select2,
            ModelAndView mav) {
         
        String res = "";
        try {
            res = "check:" + check1 + " radio:" + radio1 + " select:" + select1 + "\nselect2:";
        } catch(NullPointerException e) {}
        try {
            res += select2[0];
            for(int i = 1; i < select2.length; i++)
                res += ", " + select2[i];
            } catch (NullPointerException e) {
                res += "null";
            }
        mav.addObject("msg", res);
        mav.setViewName("index");
        return mav;
    }
}

そこそこ来てる? 学習途中はどこら辺にいるかさっぱり見当がつかないなー

[SpringBoot2.4.3] thymeleafを使う

controller

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.example.demo;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
 
@Controller
public class HelloController {
     
    @RequestMapping("/")
    public String index() {
        return "index";
    }  
}

html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        h1 {
            font-size:18px;
            font-weight:bold;
            color:gray;
        }
        body {
            font-size:13px;
            color:gray;
            margin:5px 25px;
        }
    </style>
</head>
<body>
    <h1>Helo page</h1>
    <p class="msg">This is Thymeleaf sample page.</p>
</body>
</html>

1
<p class="msg" th:text="${msg}">This is Thymeleaf sample page.</p>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.PathVariable;
 
@Controller
public class HelloController {
     
    @RequestMapping("/{num}")
    public String index(@PathVariable int num, Model model) {
        int res = 0;
        for(int i = 1; i <= num; i++)
            res += i;
        model.addAttribute("msg", "total: "+ res);
        return "index";
    }  
}

ModelはWebページで利用するデータを管理するためのクラス

### formを使う

1
2
3
4
5
6
7
8
<body>
    <h1>Helo page</h1>
    <p class="msg" th:text="${msg}">Please wait...</p>
    <form method="post" action="/">
        <input type="text" name="text1" th:value="${value}">
        <input type="submit" value="click">
    </form>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import org.springframework.stereotype.Controller;
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.servlet.ModelAndView;
 
@Controller
public class HelloController {
     
    @RequestMapping(value="/", method=RequestMethod.GET)
    public ModelAndView index(ModelAndView mav) {
        mav.setViewName("index");
        mav.addObject("msg", "お名前を書いて送信してください。");
        return mav;
    }
     
    @RequestMapping(value="/", method=RequestMethod.POST)
    public ModelAndView send(@RequestParam("text1")String str, ModelAndView mav) {
        mav.addObject("msg", "こんにちは、" + str + "さん!");
        mav.addObject("value", str);
        mav.setViewName("index");
        return mav;
    }
}

なるほどー

[SpringBoot2.4.3] RestControllerを利用する

RestControllerはビューを使わずコントローラーだけでアプリの基本部分を作成できる

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.example.demo;
 
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
public class HelloController {
     
    @RequestMapping("/")
    public String index() {
        return "Hello Spring-Boot World!";
    }
}

http://localhost:8080/
Hello Spring-Boot World!

### パラメータを渡す

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.example.demo;
 
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
public class HelloController {
     
    @RequestMapping("/{num}")
    public String index(@PathVariable int num) {
        int res = 0;
        for(int i = 1; i <= num; i++)
            res += i;
        return "total: " + res;
    }
}

http://localhost:8080/5
total: 15

おおお、一周回って基礎やると理解しやすいな。

### DataObject

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.example.demo;
 
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
public class HelloController {
     
    String[] names = {"hpscript","hanako","taro","sachiko","ichiro"};
    String[] mails = {"info@hpscript.com", "hanako@gmail.com", "taro@gmail.com","sachiko@gmail.com","ichiro@gmail.com"};
     
    @RequestMapping("/{id}")
    public DataObject index(@PathVariable int id) {
        return new DataObject(id, names[id],mails[id]);
    }
     
}
class DataObject{
     
    private int id;
    private String name;
    private String value;
     
    public DataObject(int id, String name, String value) {
        super();
        this.id = id;
        this.name = name;
        this.value = value;
    }
     
    public int getId() {return id;}
    public void setId(int id) {this.id = id;}
     
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
     
    public String getValue() {return value;}
    public void setValue(String value) {this.value = value;}
}

http://localhost:8080/2
{“id”:2,”name”:”taro”,”value”:”taro@gmail.com”}
http://localhost:8080/0
{“id”:0,”name”:”hpscript”,”value”:”info@hpscript.com”}

おおお、なんか変に感傷的になるな〜

[SpringBoot2.4.3] テストアプリケーションを作る

gradleで作ります。

1
2
3
4
5
6
7
8
9
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-mustache'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.flywaydb:flyway-core'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    runtimeOnly 'org.postgresql:postgresql'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

YAMLファイルの作成
src/main/resources/application.yml

1
2
3
4
5
6
7
8
9
spring:
  datasource:
    url:jdbc:postgresql://localhost:5432/test
    driverClassName:org.postgresql.Driver
    username:root
    password:
  mvc:
   favicon:
     enabled:false

ん? Nullにするとエラーになるな

V1__Create.sql

1
2
3
4
5
6
7
create table tsubuyaki (
    id serial primary key,
    txt varchar(100) not null,
    version integer not null default 0,
    updated_time timestamp not null default current_timestamp,
    created_time timestamp not null default current_timestamp
);

Model

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.example.demo.model;
 
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Version;
 
import org.hibernate.validator.constraints.NotEmpty;
 
@Entity
public class Tsubuyaki extends TimestampEntity {
     
    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    public long id;
     
    @NotEmpty
    public String txt;
     
    @Version
    public long version;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.example.demo.model;
 
import java.sql.Timestamp;
import java.util.Date;
 
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
 
@MappedSuperclass
public abstract class TimestampEntity {
     
    public Timestamp updatedTime;
     
    @Column(updatable=false)
    public Timestamp createdTime;
     
    @PrePersist
    public void prePersist() {
        Timestamp ts = new Timestamp((new Date()).getTime());
        this.createdTime = ts;
        this.updatedTime = ts;
    }
     
    @PreUpdate
    public void preUpdate() {
        this.updatedTime = new Timestamp((new Date()).getTime());
    }
}

Repository

1
2
3
4
5
6
7
8
9
10
package com.example.demo.repository;
 
import org.springframework.data.repository.CrudRepository;
 
import com.example.demo.model.Tsubuyaki;
 
public interface TsubuyakiRepository extends
CrudRepository<Tsubuyaki, Long>{
    Iterable<Tsubuyaki> findAllByOrderByUpdatedTimeDesc();
}

controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package com.example.demo.controller;
 
import java.util.Collections;
import java.util.Map;
 
import javax.validation.Valid;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
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.bind.annotation.RestController;
 
import com.example.demo.model.Tsubuyaki;
import com.example.demo.repository.TsubuyakiRepository;
 
@RestController @RequestMapping("/tsubuyaki")
public class TsubuyakiController {
     
    @Autowired TsubuyakiRepository repo;
     
    @RequestMapping(method=RequestMethod.POST)
    public Map<String, Tsubuyaki> create(
            @Valid @RequestBody Tsubuyaki tsubuyaki
            ){
            return Collections.singletonMap(
                    "tsubuyaki", repo.save(tsubuyaki));
         
    }
    @RequestMapping(method=RequestMethod.GET)
    public Map<String, Tsubuyaki> read(){
            return Collections.singletonMap(
                    "tsubuyaki", repo.findAllByOrderByUpdatedTimeDesc());
         
    }
    @RequestMapping(path="/{id}", method=RequestMethod.PUT)
    public void update(
            @PathVariable Long id, @RequestParam String txt
            ){
            Tsubuyaki tsubuyaki = repo.findOne(id);
            tsubuyaki.txt = txt;
            repo.save(tsubuyaki);
    }
    @RequestMapping(path="/{id}", method=RequestMethod.DELETE)
    public void delete(
            @PathVariable Long id
            ){
            repo.delete(id);
    }
     
}

ぐぬぬぬ。。。