티스토리 뷰
Spring Boot : JDBC를 이용한 FootBall Club example 6. 팀정보 검증 코드 작성 및 저장하기
Korean Eagle 2020. 6. 29. 17:38
1. 이 포스트는 축구 클럽 관리를 위한 테스트 프로젝트로 다양한 스프링 기능을 데모하기 위해 만들었다.
1-1 세션 범위의 공유객체 사용방법과 완료처리 방법
1-2 세션 객체가 존재하지 않거나 만료한 경우 처리방법(https://kogle.tistory.com/202)
1-3 SimpleJdbcInserter를 사용하는 방법
1-4 JdbcTemplate을 이용한 마지막 포스트이니 위에 프로젝트를 첨부하였다.
2. 팀작성 페이지는 input 밖에 없어 검증 작성하기가 수월하다. 아래는 검증과 저장을 수행하는 메소드를 추가하였다.
2-1 사용자가 입력한 데이터는 @modelAttribute로 받는데 @Valid를 설정하여 검증을 수행한다.
2-2 검증의 결과는 BindingResult로 받아 에러가 있는지를 확인한다.
2-3 에러가 없다면 team의 저장 로직을 수행하고 저장으로
2-3-1 완료된 team 세션 범위의 team 객체 공유를 마무리하기 위해 SessionStatus을 받아 setComplete처리를 한다.
2-3-2 이렇게 처리하면 더 이상 Session 범위에 team객체가 존재하지 않게 된다.
package pe.pilseong.fooball.controller;
import javax.validation.Valid;
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.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttribute;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
import lombok.extern.slf4j.Slf4j;
import pe.pilseong.fooball.entity.Team;
import pe.pilseong.fooball.repository.TeamRepository;
@Slf4j
@Controller
@RequestMapping("/teams")
@SessionAttributes("team")
public class TeamController {
@Autowired
private TeamRepository teamRepository;
@GetMapping
public String showTeamSetup(@SessionAttribute(required = false) Team team) {
log.info("showTeamSetup in TeamController");
if (team == null || team.getPlayers().size() == 0) {
return "redirect:/players";
}
return "team-creation";
}
@PostMapping
public String processTeamSetup(@Valid @ModelAttribute Team team, BindingResult errors, SessionStatus status) {
if (errors.hasErrors()) {
return "team-creation";
}
this.teamRepository.save(team);
log.info("processTeamSetup in TeamController :: " + team.toString() + "\n");
status.setComplete();
return "redirect:/";
}
}
3. 이 team 객체를 저장하는 TeamRepository를 다름과 같이 작성한다.
3-1 보여주기를 위한 프로젝트기 때문에 저장로직만 작성한다.
package pe.pilseong.fooball.repository;
import pe.pilseong.fooball.entity.Team;
public interface TeamRepository {
Team save(Team team);
}
3-2 TeamRepository 구현체이다.
3-2-0 지난 Player를 저장하는 것과 아주 유사하다.
3-2-0-1 우선 team을 저장한 후 저장된 team의 id를 받아 team-player 테이블에 넣어준다.
3-2-1 특이한 부분은 데이터의 저장을 위해 Player 때 사용한 JdbcTemplate 대신에 SimpleJdbcInserter를 사용한다.
3-2-1-1 생성자에서 SimpleJdbcInserter객체를 생성하는 방법에 주의한다. 특정 테이블과 매핑하는 부분이 있다.
3-2-2 ObjectMapper는 객체의 데이터를 읽어서 key와 값 형식의 Map 객체를 반환한다.
3-2-3 SimpleJdbcInsert는 Map객체를 통해 값을 받아서 데이터베이스에 저장한다.
3-2-3-1 이 Map 객체 작성을 위해 ObjectMapper 클래스를 사용한 것 뿐이다.
3-2-3-2 key가 다른 경우 그냥 반환된 map 객체에 put으로 추가하거나 삭제하면 된다.
3-2-2 SimpleJdbcInsert도 PreparedStatementFactory처럼 id를 반환할 수 있는데 좀 더 단순하다.
3-2-2-1 별도의 KeyHolder가 필요없다.
3-2-2-2 저장 할 때 executeAndReturnKey를 사용하여 id를 반환 받을 수 있다.
package pe.pilseong.fooball.repository;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.stereotype.Repository;
import lombok.extern.slf4j.Slf4j;
import pe.pilseong.fooball.entity.Player;
import pe.pilseong.fooball.entity.Team;
@Slf4j
@Repository
public class TeamRepositoryImpl implements TeamRepository {
private SimpleJdbcInsert teamInserter;
private SimpleJdbcInsert teamPlayerInserter;
private ObjectMapper objectMapper;
@Autowired
public TeamRepositoryImpl(JdbcTemplate jdbc) {
this.teamInserter = new SimpleJdbcInsert(jdbc).withTableName("team").usingGeneratedKeyColumns("id");
this.teamPlayerInserter = new SimpleJdbcInsert(jdbc).withTableName("teams_players");
this.objectMapper = new ObjectMapper();
}
@Override
public Team save(Team team) {
team.setCreatedAt(new Date());
Long teamId = saveTeamDetails(team);
team.setId(teamId);
team.getPlayers().forEach(player -> {
saveTeamsPlayers(player, teamId);
});
log.info("save in TeamRepositoryImpl");
return null;
}
private void saveTeamsPlayers(Player player, Long teamId) {
Map<String, Long> values = new HashMap<>();
values.put("team_id", teamId);
values.put("player_id", player.getId());
this.teamPlayerInserter.execute(values);
}
private Long saveTeamDetails(Team team) {
@SuppressWarnings("unchecked")
Map<String, Object> teamMap = this.objectMapper.convertValue(team, Map.class);
@SuppressWarnings("unchecked")
Map<String, Object> addressMap = this.objectMapper.convertValue(team.getAddress(), Map.class);
teamMap.putAll(addressMap);
teamMap.put("created_at", team.getCreatedAt());
log.info("saveTeamDetails in TeamRepositoryImpl :: " + teamMap.toString());
return this.teamInserter.executeAndReturnKey(teamMap).longValue();
}
}
4. 결과 화면
4-1 아무것도 입력하지 않고 submit했을 때 화면
4-2 팀을 하나 만들고 등록한 데이터베이스 결과
4-2-1 선수는 나밖에 없다 ㅋㅋㅋ
4-2-2 대한민국 팀에도 나밖에 등록이 안되어 있다. 당연하게 나만 등록했으니
'Demos > Football Club' 카테고리의 다른 글
Spring Security : FootBall Club example에 Security 적용하기 (0) | 2020.07.01 |
---|---|
Spring Boot : JPA를 이용한 FootBall Club example (0) | 2020.06.29 |
Spring Boot : JDBC를 이용한 FootBall Club example 5. 팀정보 구성하기 (0) | 2020.06.29 |
Spring Boot : JDBC를 이용한 FootBall Club example 4. 선수 저장하기 (0) | 2020.06.29 |
Spring Boot : JDBC를 이용한 FootBall Club example 3. 선수 등록 검증로직 작성 (0) | 2020.06.29 |
- Total
- Today
- Yesterday
- 도커 개발환경 참고
- AWS ARN 구조
- Immuability에 관한 설명
- 자바스크립트 멀티 비동기 함수 호출 참고
- WSDL 참고
- SOAP 컨슈머 참고
- MySql dump 사용법
- AWS Lambda with Addon
- NFC 드라이버 linux 설치
- electron IPC
- mifare classic 강의
- go module 관련 상세한 정보
- C 메모리 찍어보기
- C++ Addon 마이그레이션
- JAX WS Header 관련 stackoverflow
- SOAP Custom Header 설정 참고
- SOAP Custom Header
- SOAP BindingProvider
- dispatcher 사용하여 설정
- vagrant kvm으로 사용하기
- git fork, pull request to the …
- vagrant libvirt bridge network
- python, js의 async, await의 차이
- go JSON struct 생성
- Netflix Kinesis 활용 분석
- docker credential problem
- private subnet에서 outbound IP 확…
- 안드로이드 coroutine
- kotlin with, apply, also 등
- 안드로이드 초기로딩이 안되는 경우
- navigation 데이터 보내기
- 레이스 컨디션 navController
- raylib
- Angular
- 스프링부트
- 외부파일
- 자바
- spring boot
- 설정
- 설정하기
- 스프링
- RestTemplate
- 하이버네이트
- Many-To-Many
- WebMvc
- MYSQL
- Rest
- login
- Security
- Spring Security
- 로그인
- jsp
- one-to-many
- mapping
- XML
- crud
- 상속
- Validation
- one-to-one
- form
- 매핑
- hibernate
- Spring