Post

Spring - 1 스프링 에제 프로젝트 PetClinic

해당 자료는 인프런 백기선님의 예제로 배우는 스프링 입문(개정판) 강의노트입니다..


1. 프로젝트 설정

준비물은 Intellij입니다.
https://github.com/spring-projects/spring-petclinic 해당 URL에서 적당한 폴더에 git clone을 해줘서 프로젝트를 가져오고 intellij에서 열어줬습니다.

강의를 보면 git bash가 intellij와 연동되어 있지만, 저는 연동되어 있지 않았습니다.

https://violetboralee.medium.com/intellij-idea%EC%99%80-git-bash-%EC%97%B0%EB%8F%99%ED%95%98%EA%B8%B0-63e8216aa7de
이 블로그를 통해 cmd에서 gitbash로 바꿀 수 있었습니다.

그리고 해당 깃 Readme.md에 있는 순서대로 초기설정을 해주었습니다.

1
2
./mvnw package
java -jar target/*.jar //jar파일을 실행함.

<localhost:8080>으로 확인

이후 FIND OWNERS 탭에서 ADD Owner와 ADD Pet을 통해 정보를 추가.

또한, Add visit을 통해 방문일정을 추가해주었습니다.

  • 예전에 배운 Intellij에서 main method를 run을 시켜 실행해버리는 것은 ./mvnw package(메이븐 패키징)를 안해주면 오류가 날 수 있다고합니다. 플러그인이 먼저 동작해야하는데 하지 않으면 로컬에서 화면이 깨질 수도 있습니다.

2. 프로젝트 살펴보기

해당 웹이 어떻게 돌아가는 지 알려주셨다.

Log를 찍기 위해 application.properties에서 주석문을 제거해줍니다.

1
logging.level.org.springframework.web=DEBUG

  • 디버거 찍는법은 vs와 같이 빨간점으로 찍고 디버그모드로 돌리면 된다.

3. 프로젝트 과제 풀이

  • LastName이 아니라 FirstName으로 검색해 볼까?
  • 정확히 일치하는게 아니라 해당 키워드가 들어있는 걸 찾아볼까?
  • Owner에 age 추가

이 세가지를 고치기로 했습니다.

3.1. LastName을 FirstNamed으로 바꾸기

화면에 보이는 Lastname을 Firstname으로 바꾸기위해 findOwners.html에서

1
2
<input class="form-control" th:field="*{Lastname}" size="30" 
-> <input class="form-control" th:field="*{firstName}" size="30"

OwnerController.java 파일에서

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
@GetMapping("/owners")
	public String processFindForm(Owner owner, BindingResult result, Map<String, Object> model) {

		// allow parameterless GET request for /owners to return all records
		if (owner.getFirstName() == null) {
			owner.setFirstName(""); // empty string signifies broadest possible search
		}

		// find owners by first name
		Collection<Owner> results = this.owners.findByFirstName(owner.getFirstName());
		if (results.isEmpty()) {
			// no owners found
			result.rejectValue("lastName", "notFound", "not found");
			return "owners/findOwners";
		}
		else if (results.size() == 1) {
			// 1 owner found
			owner = results.iterator().next();
			return "redirect:/owners/" + owner.getId();
		}
		else {
			// multiple owners found
			model.put("selections", results);
			return "owners/ownersList";
		}
	}

이렇게 LastName과 관련된 메소드를 다 firstName메소드로 바꿔줍니다.

또한 OwnerRepository.java 파일에서

1
2
3
@Query("SELECT DISTINCT owner FROM Owner owner left join fetch owner.pets WHERE owner.firstName LIKE :firstName%")
	@Transactional(readOnly = true)
	Collection<Owner> findByFirstName(@Param("firstName") String firstName);

이렇게 새로운 Query문을 만들어주고 firstName()을 반환하도록 합니다.

3.2. 정확히 일치하는게 아니라 해당 키워드가 들어있는 걸 찾아볼까?

위에서 작성한 쿼리문을 수정해줍니다.

1
2
3
@Query("SELECT DISTINCT owner FROM Owner owner left join fetch owner.pets WHERE owner.firstName LIKE %:firstName")
	@Transactional(readOnly = true)
	Collection<Owner> findByFirstName(@Param("firstName") String firstName);
  • :%firstName이 아닌 %:firstName으로 적어야 :firtName이 매개변수로 치환된다고 합니다.

3.3.Owner에 age 추가

Owner.java 파일에

1
2
3
4
5
6
7
8
9
private Integer age;

public Integer getAge() {
		return age;
	}

public void setAge(Integer age) {
    this.age = age;
}

을 추가해주고 서버를 재시작하면 DB에 age가 없기에 Query문 오류가 납니다.

따라서 resources/db/hsqldb/schema.sql을 수정해줘야합니다.


age INTERGER를 추가해주고, INSERT문에서 age도 추가해주기 위해 /resources/db/hsqldb/data.sql에 임의의 나이를 설정해줍니다.

1
2
3
4
5
6
7
8
9
10
INSERT INTO owners VALUES (1, 'George', 'Franklin', 20, '110 W. Liberty St.', 'Madison', '6085551023');
INSERT INTO owners VALUES (2, 'Betty', 'Davis',20, '638 Cardinal Ave.', 'Sun Prairie', '6085551749');
INSERT INTO owners VALUES (3, 'Eduardo', 'Rodriquez',20, '2693 Commerce St.', 'McFarland', '6085558763');
INSERT INTO owners VALUES (4, 'Harold', 'Davis',20, '563 Friendly St.', 'Windsor', '6085553198');
INSERT INTO owners VALUES (5, 'Peter', 'McTavish',20, '2387 S. Fair Way', 'Madison', '6085552765');
INSERT INTO owners VALUES (6, 'Jean', 'Coleman',20, '105 N. Lake St.', 'Monona', '6085552654');
INSERT INTO owners VALUES (7, 'Jeff', 'Black',20, '1450 Oak Blvd.', 'Monona', '6085555387');
INSERT INTO owners VALUES (8, 'Maria', 'Escobito',20, '345 Maple St.', 'Madison', '6085557683');
INSERT INTO owners VALUES (9, 'David', 'Schroeder',20, '2749 Blackhawk Trail', 'Madison', '6085559435');
INSERT INTO owners VALUES (10, 'Carlos', 'Estaban',20, '2335 Independence La.', 'Waunakee', '6085555487');

화면에서 나이를 물어봐야하기때문에 createOrUpdateOwnerForm.html도 고쳐줘야합니다.

1
2
<input
        th:replace="~{fragments/inputField :: input ('Age', 'age', 'text')}" />

다음 코드를 추가해줍니다.

쿼리문을 보내려하면 에러가 뜨는데 강의 버전이랑 clone한 프로젝트 버전이 달라서 application.proterties를 바꿔줘야합니다.

1
2
database=h2 
database=hsqldb로 바꿔줍니다.

검색을 했을 때 나이를 출력해주기 위해

ownerList.html의 코드를 손봐줍시다.

1
2
<th style="width: 200px;">Age</th>
<td th:text="${owner.age}"/>

이렇게 추가해주면


성공적으로 들어가는 것을 볼 수 있습니다.

또한 User를 누르면 age에 대한 정보가 누락되어있으므로 해당사항도 해결해주어야 합니다.

ownerDetails.html에서 코드를 추가해줍니다.

1
2
3
4
5
6
~
      <tr>
        <th>Age</th>
        <td><b th:text="*{age}"></b></td>
      </tr>
~

성공했고 마지막에 유저를 임의적으로 만들었을 때 제대로 들어가는 지 확인해봅니다.

제대로 들어갔습니다.


This post is licensed under CC BY 4.0 by the author.