[Spring Boot2.4.2] SpringJDBCでselect

pom.xml

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<scope>runtime</scope>
		</dependency>

Syain.java

package com.example.demo;

public class Syain {
	
	private Integer id;
	private String name;
	private String romaji;
	
	public Integer getId() {
		return id;
	}
	public String getName() {
		return name;
	}
	public String getRomaji() {
		return romaji;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public void setName(String name) {
		this.name = name;
	}
	public void setRomaji(String romaji) {
		this.romaji = romaji;
	}
}

SyainRepository.java
L mapとは、「キー」と「値」をペアにして複数のデータを格納できるもの
-> 連想配列みたいなものか。。

package com.example.demo;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class SyainRepository {
	private final JdbcTemplate jdbcTemplate;
	
	@Autowired
	public SyainRepository(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}
	
	public List<Syain> getAll(){
		String sql = "select id, name, romaji from syain";
		List<Map<String, Object>>syainList = jdbcTemplate.queryForList(sql);
		List<Syain> list = new ArrayList<>();
		for(Map<String,Object> str1: syainList) {
			Syain syain = new Syain();
			syain.setId((int)str1.get("id"));
			syain.setName((String)str1.get("name"));
			syain.setRomaji((String)str1.get("romaji"));
			list.add(syain);
		}
		return list;
	}
}

MainController.java

package com.example.demo;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/test1")
public class MainController {
	@Autowired
	private SyainRepository syainRepository;
	
	@GetMapping
	public String index(Model model) {
		List<Syain> list = syainRepository.getAll();
		model.addAttribute("SyainList", list);
		return "test1/index";
	}
}

index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8" />
    <title>Check</title>
  </head>
  <body>
    <table>
    	<tr>
    		<th>id</th><th>name</th><th>romaji</th>
    	</tr>
    	<tr th:each="list : ${SyainList}">
    		<td th:text="${list.id}"></td>
    		<td th:text="${list.name}"></td>
    		<td th:text="${list.romaji}"></td>
    	</tr>
    </table>
  </body>
</html>

なんかもう殆どSpringBootでアプリ作れるような気がしてきた。

[Spring Boot2.4.2] Postgresからselect

### Postgresにデータ挿入
psql -U root test
CREATE TABLE syain (
id SERIAL NOT NULL,
name varchar(255),
romaji varchar(255),
PRIMARY KEY(id)
);

INSERT INTO syain (name, romaji) VALUES (‘鈴木’,’suzuki’);
INSERT INTO syain (name, romaji) VALUES (‘田中’,’tanaka’);
INSERT INTO syain (name, romaji) VALUES (‘佐藤’,’sato’);
test=> select * from syain;
id | name | romaji
—-+——+——–
1 | 鈴木 | suzuki
2 | 田中 | tanaka
3 | 佐藤 | sato
(3 rows)

pom.xml

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<scope>runtime</scope>
		</dependency>

application.properties

spring.jpa.database=POSTGRESQL
spring.datasource.url=jdbc:postgresql://localhost:5432/test
spring.datasource.username=root
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.properties.hibernate.format_sql=true
spring.datasource.sql-script-encoding=UTF-8

Syain.java

package com.example.demo;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Id;

@Entity
@Table(name="syain")
public class Syain {
	@Id
	private Integer id;
	private String name;
	private String romaji;
	
	public Integer getId() {
		return id;
	}
	public String getName() {
		return name;
	}
	public String getRomaji() {
		return romaji;
	}
}

SyainRepository.java

package com.example.demo;
import org.springframework.data.jpa.repository.JpaRepository;

public interface SyainRepository extends JpaRepository<Syain, Integer>{
}

MainController.java

package com.example.demo;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MainController {
	@Autowired
	private SyainRepository syainRepository;
	
	@GetMapping("/test1")
	public List<Syain> get() {
		return syainRepository.findAll();
	}
}

うおおおおおおおおおおおおおおおおお
きたあああああああああああああああああああああああ

[Spring Boot2.4.2] Thymeleafで共通レイアウトを使用する

src/main/resources/templates/test1/partial1.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<header th:fragment="header1">
<p style="background:yellow;">ヘッダーです</p>
</header>
<footer th:fragment="footer1">
<p style="background:yellow;">フッターです</p>
</footer>
</html>

src/main/resources/templates/test1/index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8" />
    <title>Check</title>
  </head>
  <body>
    <div th:replace="text1/partial1::header1"></div>
    <p>テスト</p>
    <div th:replace="text1/partial1::footer1"></div>
  </body>
</html>

MainController.java

package com.example.demo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/test1")
public class MainController {
	
	@GetMapping
	public String index() {
		return "test1/index";
	}
}

ほう、中々面白い

地道にやってくのが手堅いか。。

### Bootstrapを追加
pom.xml

		<dependency>
			<groupId>org.webjars</groupId>
			<artifactId>bootstrap</artifactId>
			<version>4.5.2</version>
		</dependency>

index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8" />
    <link rel="stylesheet" th:href="@{/webjars/bootstrap/4.5.2/css/bootstrap.min.css}">
    <title>Check</title>
  </head>
  <body>
    <span class="badge badge-primary">Primary</span>
<span class="badge badge-secondary">Secondary</span>
<span class="badge badge-success">Success</span>
<span class="badge badge-danger">Danger</span>
<span class="badge badge-warning">Warning</span>
<span class="badge badge-info">Info</span>
<span class="badge badge-light">Light</span>
<span class="badge badge-dark">Dark</span>
  </body>
</html>

pom.xmlの反映は、コンパイルし直さないといけない。

[Spring Boot2.4.2] JSONの送受信

src/main/resources/templates/test1/index.html

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
  </head>
  <body>
    <p id="p1"></p>
    <p id="p2"></p>
  </body>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
		$("#p1").text("");
		$("#p2").text("");
        var json1 = {
			bangou: "1",
			name: "鈴木",
		};
		$.ajax({
		url: "http://localhost:8080/test1/index",
		type: "POST",
		contentType: "application/json",
		data: JSON.stringfy(json1),
		dataType: "json",
		})
		.done(function (data1, textStatus, jqXHR){
			$("#p1").text(jqXHR.status);
			$("#p2").text(JSON.stringify(data1));
		})
		.fail(function (jqXHR, textStatus, errorThrown){
			$("#p1").text(jqXHR.status);
		})
		.always(function() {});
</script>
</html>

Syain.java

package com.example.demo;
import java.io.Serializable;

public class Syain implements Serializable {
	private static final long serialVersionUID = 1L;
	
	private String bangou;
	private String name;
	
	public String getBangou() {
		return bangou;
	}
	public void setBangou(String bangou) {
		this.bangou = bangou;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

MainController.java
L @ResponseBodyはコントローラからの戻り値を返す
L

package com.example.demo;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test1")
public class MainController {
	
	@PostMapping("/index")
	@ResponseBody
    public Syain output1(
    		@RequestBody Syain syain) {
				System.out.println(syain.getBangou());
				System.out.println(syain.getName());
				return syain;
	}
}

2021-02-07 12:07:42.608 INFO 44783 — [ restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 772 ms
2021-02-07 12:07:42.743 INFO 44783 — [ restartedMain] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService ‘applicationTaskExecutor’
2021-02-07 12:07:42.889 INFO 44783 — [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2021-02-07 12:07:42.919 INFO 44783 — [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ”
2021-02-07 12:07:42.927 INFO 44783 — [ restartedMain] com.example.demo.TestApplication : Started TestApplication in 1.355 seconds (JVM running for 7.09)
2021-02-07 12:08:35.401 INFO 44783 — [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet ‘dispatcherServlet’
2021-02-07 12:08:35.401 INFO 44783 — [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet ‘dispatcherServlet’
2021-02-07 12:08:35.402 INFO 44783 — [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
2021-02-07 12:08:37.410 WARN 44783 — [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method ‘GET’ not supported]

うーむ、上手く表示されんな。。

[Spring Boot2.4.2] AOP(アスペクト指向プログラミング)

pom.xml

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>

AOPファイル TestLog.java

package com.example.demo;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class TestLog {
	
	@After("within(com.example.demo.MainController)")
	public void write1() {
		System.out.println("ログイン後");
	}
}

@AspectはAOPとして動作
@After, @Before, @Around, @AfterReturning, @AfterThrowing などがある。

MainController.java

package com.example.demo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MainController {
	
	@GetMapping("/test1")
    public String input1() {
        return "test1";
    }
	
	@GetMapping("/test2")
	public String input2(){
        return "test2";
    }
}

Error starting ApplicationContext. To display the conditions report re-run your application with ‘debug’ enabled.
2021-02-07 11:29:27.692 ERROR 43506 — [ restartedMain] o.s.boot.SpringApplication : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘requestMappingHandlerMapping’ defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map ‘test1’ method
com.example.demo.Test1#write1()
to {GET [/test2]}: There is already ‘mainController’ bean method
com.example.demo.MainController#input2() mapped.

ん? 何故だ??

[Spring Boot2.4.2] DI(依存性注入)を理解する

Syain.java (service)
L @ServiceでDIコンテナに登録する

package com.example.demo;
import org.springframework.stereotype.Service;

@Service
public class Syain {
	public String getName() {
		return "tanka";
	}
}

MainController.java
L Autowiredとは、自動的にクラスのプロパティ(setter)や、メンバ変数に値を設定する機能

package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MainController {
	@Autowired
	Syain syain;
	
	@GetMapping("/test1")
	public String write1() {
		return syain.getName();
	}
}

ほう、、、

### アプリ起動時にインスタンスを取得する
Syain.java

package com.example.demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
 L @BeanはSpring起動時に設定の内容を取り込む
public class Syain {
	@Bean
	public String getName() {
		return "sato";
	}
}

TestApplication.java

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

@SpringBootApplication
public class TestApplication {

	public static void main(String[] args) {
		ApplicationContext syain = new AnnotationConfigApplicationContext(Syain.class);
		SpringApplication.run(TestApplication.class, args);
	}

}

@Beanって起動時の設定のことか、豆の印象が強すぎてイマイチ頭に入って来んかった。。

[Spring Boot2.4.2] フォームとエンティティの連携

エンティティとは?
-> relational databaseの表を表す

src/main/resources/templates/test1/index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>check</title>
</head>
<body >
<form method="post" action="#" th:action="@{/test1/testform}" th:object="${test1Form}">
<p><input type="text" id="id" name="id" th:field="*{id}"/></p>
<p><input type="text" id="name" name="name" th:field="*{name}"></p>
<p><input type="submit" value="送信ボタン"></p>
</form>
</body>
</html>

フォームクラス: Test1Form.java
L controllerのmodel.addAttribute(“test1Form”, new Test1Form());でvalidationをかけている

package com.example.demo;

public class Test1Form {
	private Integer id;
	private String name;
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

エンティティのクラス: Syain.java (社員)
L formのvalidationと同じく、privateで宣言して、geter, setterを書く
L getter, setterは、データを外部から取得するメソッド、あるいはそのデータを外部から変更するメソッド

package com.example.demo;

public class Syain {
	private Integer id;
	private String name;
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

MainController.java

package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Controller
@RequestMapping("/test1")
public class MainController {
	@Autowired
	private SyainRepository syainRepository;
	
    @GetMapping
    public String disp1(
    		Model model) {
    	model.addAttribute("test1Form", new Test1Form());
        return "test1/index";
    }
    @PostMapping("/testform")
	public String disp2(Test1Form test1Form) {
		    Syain syain = new Syain();
		    syain.setId(test1Form.getId());
		    syain.setName(test1Form.getName());
		    syainRepository.insertSyain(syain);
			return "redirect:/test1/";
		}
}

pom.xml

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>

SyainRepository.java

package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class SyainRepository {
	private final JdbcTemplate jdbcTemplate;
	
	@Autowired
	public SyainRepository(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}
	
	public void insertSyain(Syain syain) {
		jdbcTemplate.update("INSERT INTO syain(id,name) VALUES (?, ?)",
				syain.getId(), syain.getName());
	}
}

Description:

Failed to configure a DataSource: ‘url’ attribute is not specified and no embedded datasource could be configured.

Reason: Failed to determine a suitable driver class

なるほど、何となくわかってきた。

[Spring Boot2.4.2] フォームの値のバリデーション

pom.xml

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-validation</artifactId>
		</dependency>

src/main/resources/templates/test1/index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>submit</title>
</head>
<body >
<form method="post" action="#" th:action="@{/test1/testform}" th:object="${test1Form}">
<p><input type="text" id="id" name="id" th:field="*{id}"/></p>
<div th:if="${#fields.hasErrors('id')}" th:errors="*{id}"></div>

<p><input type="text" id="name" name="name" th:field="*{name}"></p>
<div th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></div>
<p><input type="submit" value="送信ボタン"></p>
</form>
</body>
</html>

MainController.java

package com.example.demo;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Controller
@RequestMapping("/test1")
public class MainController {
	
    @GetMapping
    public String disp1(
    		Model model) {
    	model.addAttribute("test1Form", new Test1Form());
        return "test1/index";
    }
    @PostMapping("/testform")
	public String disp2(@Validated Test1Form test1Form
			,BindingResult br) {
		        if (br.hasErrors()) {
		        	return "test1/index";
		        }
			return "test1/testform";
		}
}

Test1Form.java

package com.example.demo;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class Test1Form {
	@NotNull(message="必須項目です")
	private Integer id;
	
	@Size(min=3, max=6, message="3文字から6文字で入力して下さい")
	private String name;
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

src/main/resources/templates/test1/testform.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>submit</title>
</head>
<body >

<p>OK</p>

</body>
</html>

やべええええええええええええ
SpringBoot面白いかも。

[Spring Boot2.4.2] Thymeleafを使って値を渡す

pomにdependenciesを追加する

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>

src/main/resources/templates/test1/testform.html

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>submit</title>
</head>
<body>
<form method="get" action="testform">
<input type="text" name="text1">
<input type="submit" value="送信ボタン">
</form>
</body>
</html>

com.example.demo/MainController.java
L @RequestParamはリクエストされたパラメータを受け取り、変数str1にsetする
L addAttributeで変数str1をセット

package com.example.demo;

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

@Controller
@RequestMapping("/test1")
public class MainController {
	
	@GetMapping
	public String input1() {
		return "test1/index";
	}
	
	@GetMapping("testform")
	public String output1(
			@RequestParam(name = "text1") String str1,
			Model model) {
			model.addAttribute("moji1", str1);
			return "test1/testform";
	}
	
}

src/main/resources/templates/test1/index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>submit</title>
</head>
<body>
<p th:text="${moji1}"></p>

</body>
</html>

上手くいかないが、何故上手くいかないのかよくわからん。

[Spring Boot2.4.2] プロジェクト作成

Test1.java

package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Test1 {
	
	@GetMapping("/test1")
	public String write1() {
		return "Hello World1";
	}
}

RestControllerはメソッドの戻り値を画面に表示する
@GetMappingは@RequestMapping(method=RequestMethod.GET)と同じ意味
Run As -> Spring boot
http://localhost:8080/test1
Hello World1

application.properties

server.port=8756

pom.xml

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>true</scope>
		</dependency>

spring-boot-devtoolsをtrueにするとファイルを更新した際に、アプリを再起動しなくても更新される。