| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- Algorism study
- 내일배움카드
- Interface
- #패스트캠퍼스 #국비지원교육 #메가바이트스쿨 #MegabyteSchool #개발자취업부트캠프 #내일배움카드
- MegabyteSchool
- 클래스 상속
- View
- Java
- Sts
- spring boot
- 게시판 리뷰 만들기
- AWS
- 클래스 class
- array
- 게시판 만들기
- 국비지원교육
- #javaStudy
- tomcat
- Spring
- Entity
- 패스트캠퍼스
- MVC
- MVC 패턴
- crud
- 개발자취업부트캠프
- 메가바이트스쿨
- group study
- GIT
- side project
- github
- Today
- Total
tuter77
게시판 만들기(6) 엔티티 연관관계 설정 및 view구현. 본문
● 연관관계 엔티티 피드백 및 다음 과제
▷ 연관관계 엔티티
Review와 healthInfo 엔티티를 봤을때, 팀장님이 내가 작성한 엔티티에서 List를 활용한 구문을 짚어주셨다.
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "healthInfo")
private List<Review> reviews = new ArrayList<>();
이 구문에서 로딩방식을 Lazy로 적용한 것과 엔티티의 상태변화를 적용할 cascade를 활용한 점이 좋았다고 했다.
또한 아래의 List로 생성한 이유를 아느냐고 했는데, 나는 이유를 몰랐었다.
설명해주신 부분은 댓글이 없는 경우에 null에러 예외를 방지하고자 이렇게 선언한다고 한다.
전반적으로 코드가 깔끔하게 짜여있다고 칭찬받았다.
▷다음 과제
기존의 healthInfo를 활용해 get, post mapping으로 정보를 가져오거나 저장할 수 있는 페이지를 구현하라는 과제를 받았다.
특히 저장하는 과정에서 정보를 조회하는 페이지 > 저장페이지 > 다시 조회 페이지로 재요청을 보내도록 하는것을 PRG패턴이라고 했는데 이 방식을 적용하라고 팁을 주셨다.
또한 이 과제에서 MVC 패턴을 학습하기를 바란다고 하셨는데, 일단은 Spring강의를 통해 MVC 패턴에 대해 좀 알아보아야 한다.
정리하면 MVC 패턴을 학습하기 위해 Html 파일을 두 가지를 만들고 (데이터 조회용, 저장용) 해당 페이지의 기능을 구현할 HomeController를 만들면 된다.
● html 파일 완성 및 read, save 기능 구현.
▷ html
먼저 html 파일 2개를 어제 완성했는데 오늘 피드백 받아보니 몇군데 수정사항이 있었다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
<meta charset="UTF-8">
<title>헬스장 정보 리스트 페이지</title>
</head>
<style>
.layout {
width: 500px;
margin: 0 auto;
margin-top: 40px;
}
</style>
<body>
<table>
<thead>
<tr>
<h1>제목</h1>
</tr>
</thead>
<tbody>
<tr th:each = "healthInfo:${list}">
<td th:text="${healthInfo.id}"></td>
<td th:text="${healthInfo.brand_name}"></td>
<td th:text="${healthInfo.land_number}"></td>
<td th:text="${healthInfo.road_number}"></td>
<td th:text="${healthInfo.category}"></td>
</tr>
</tbody>
</table>
</body>
</html>
home.html 로 기본 페이지가 되는 형태이다. 아래에 타임리프문을 적용한 반복문의 healthInfo 부분을 수정했고, 브랜드 넘버로 되어있던것을 브랜드 네임으로 수정했다.
위 구분은 홈서비스에서 리스트로 저장되는 값들을 반복문이 돌아가면서 페이지에 보여주는 형태이다.
결과물)

이와 같이 /home을 url에 요청해주면, 웹브라우저에 리스트의 형태로 데이터가 잘 표현되는 것을 볼 수 있었다.(갓 팀장님..)
이제 read는 했으니 저장을 만들 차례이다.
기본 골조는 저장버튼을 누르면, 저장하는 페이지로 넘어가고 해당 페이지에서 데이터를 입력한 뒤 저장하는 형태로 만드려고한다.
저장 기능을 구현하기 전에 보기에 너무 어지러워서 상세페이지 작업을 먼저했다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
<meta charset="UTF-8">
<title>헬스장 정보 리스트 페이지</title>
</head>
<body>
<table>
<thead>
<tr>
<h1>Homepage</h1>
<button type="submit" onclick="location.href='home/post'">데이터 입력</button>
</tr>
</thead>
<tbody>
<tr th:each = "healthInfo:${list}">
<td th:text="${healthInfo.id}"></td>
<td>
<a th:text="${healthInfo.brand_name}"
th:href="@{/home/view(id=${healthInfo.id})}">
</a>
</td>
</tr>
</tbody>
</table>
</body>
</html>
기존 home.html페이지에서는 id와 brand_name만 볼 수 있게하고 다른 내용들은 해당 brand_name을 클릭하면 상세페이지로 넘어가 볼 수 있게 했다.
여기서 반복문을 사용해 모든 값들을 다 찾아오는 것은 동일하나 brand_name에 a태그를 붙여 상세페이지로 넘어가게 작업했다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
<meta charset="UTF-8">
<title>상세페이지</title>
</head>
<body>
<h1 th:text="${healthInfo.brand_name}"></h1>
<p th:text="${healthInfo.land_number}"></p>
<p th:text="${healthInfo.road_number}"></p>
<p th:text="${healthInfo.category}"></p>
<button type="submit" onclick="location.href='/home'">뒤로</button>
</body>
</html>
위는 상세페이지로 앞서 만들었던 모든 값을 다 가져오는 형태와 유사하지만, a태그 brand_name을 누르면 해당 id값을 통해 다른 내용들을 불러올 수 있게 만들었다.
여기서 id값이 조회되지않아 한참을 헤맸는데 팀장님이 컨트롤러와 서비스에 빈등록 및 생성자 어노테이션을 빼먹어서 발생한 오류라는 내용으로 겨우 해결할 수 있었다.
@RequiredArgsConstructor
@Controller
@Slf4j
public class HomeController {
private final HealthRepository healthRepository;
private final HomeService homeService;
//기본형태
@GetMapping("/home") //url localhost:8080/home
public String home(Model model) {
model.addAttribute("list", healthRepository.findAll());
return "home";
}
@GetMapping("/home/view")
public String healthView(Model model,@RequestParam Long id){
model.addAttribute("healthInfo", homeService.healthView(id));
return "healthview";
}
}
메인 컨트롤러에는 @Controller로 빈등록을 하고, private final로 선언된 생성자 호출을 하기위해선@RequiredArgsConstructor 어노테이션이 필요했다.
이 과정이 없었기 때문에 각 값들이 null로 계속 표기되어있었던 것이다.
여하튼 아래의 healthView 메서드를 보면, 파라미터로 id값을 받아 서비스의 healthView라는 메서드로 값들을 찾아오게 되어있다.
반환 값은 앞에서 살펴본 상세페이지 html파일이다.
@Service
@RequiredArgsConstructor
public class HomeServiceImpl implements HomeService {
private final HealthRepository healthRepository;
@Override
public void write(HealthInfo healthInfo) {
healthRepository.save(healthInfo);
}
@Override
public List<HealthInfo> HealthList() {
List<HealthInfo>list=healthRepository.findAll();
return list;
}
@Override
public HealthInfo healthView(Long id) {
System.out.println(id);
return healthRepository.findById(id).orElseThrow(IllegalArgumentException::new);
}
}
이는 Service 인터페이스의 구현체로 healthView가 findById메서드로 나머지 값들을 레포지토리에서 조회해하는 것을 볼 수 있다. 혹여나 null값 오류가 발생할 것을 대비해 null값 오류라는 예외처리구문을 출력하는 orElseThrow메서드도 사용했다.
id값 조회에서 null오류가 계속 발생해 몇시간을 날려버린 자신에게 너무 화가나는 과정이었다.
위 내용은 2023.01.11에 공부한 내용입니다.
'GroupStudy' 카테고리의 다른 글
| 게시판 만들기(8) - update 구현 (0) | 2023.01.29 |
|---|---|
| 게시판 만들기(7) - 저장, 삭제 기능 구현 (0) | 2023.01.29 |
| 게시판 만들기(5) - review 엔티티 만들기. (0) | 2023.01.29 |
| 게시판 만들기(4) - 데이터를 입력하여 CRUD구현. (0) | 2023.01.29 |
| 게시판 만들기 : ManyToOne 조사 (0) | 2023.01.29 |