1. 환경
1. Sping Boot
2. Spring Data JPA
3. Gradle
4. postgreSQL
5. PostMan
6. Swagger
7. 인텔리제이 무료버전
2. DB 구조
3. CRUD 구현
(1). Entity 생성
@Entity
@Getter
@Setter
@ToString
@Table(name = "room_cd")
public class EclassRoomEntity {
@Id
@Column(name = "room_cd_id", length = 36)
private String roomCdId;
@Column(nullable = false, length = 100)
private String roomNm; // 강의실명
@Column(nullable = false)
private int hdcnt; // 정원, headCount
@Column(length = 1, columnDefinition = "varchar (1) default 'N'")
private String useYn; // 사용여부
/* 기본 생성자 추가 */
public EclassRoomEntity() {
}
/* 초기화용 생성자 */
public EclassRoomEntity(String roomCdId) {
this.roomCdId = roomCdId;
}
/* @Builder = 생성자 자동 생성 */
@Builder
public EclassRoomEntity(String roomCdId, String roomNm, int hdcnt, String useYn) {
this.roomCdId = roomCdId;
this.roomNm = roomNm;
this.hdcnt = hdcnt;
this.useYn = useYn;
}
}
(2). DTO 생성
@Data // @Data = @Getter, @Setter, @ToString, @EqualsAndHashCode, @RequiredArgsConstructor
public class EclassRoomDTO {
private String roomCdId; // 강의실 코드
private String roomNm; // 강의실명
private int hdcnt; // 정원
private String useYn; // 사용여부
// 기본 생성자
public EclassRoomDTO() {
}
public EclassRoomDTO(String roomCdId, String roomNm, int hdcnt, String useYn) {
}
/* ex) DB에서 조회할 때 강의실 정보를 Entity 객체에 담아오고, DTO로 변환하여 클라이언트에게 전달 */
public static EclassRoomDTO toDTO(EclassRoomEntity entity) { // Entity -> DTO 변환
EclassRoomDTO dto = new EclassRoomDTO(); // DTO 객체 생성
dto.setRoomCdId(entity.getRoomCdId());
dto.setRoomNm(entity.getRoomNm());
dto.setHdcnt(entity.getHdcnt());
dto.setUseYn(entity.getUseYn());
return dto;
}
}
(3). DTO -> Entity 변환 클래스 생성
public class EclassRoomEntityBuilder {
public static EclassRoomEntity buildFromDTO(EclassRoomDTO eclassRoomDTO) { // DTO -> Entity 변환
return EclassRoomEntity.builder() // builder을 이용하여 entity 객체 생성
.roomCdId(eclassRoomDTO.getRoomCdId())
.roomNm(eclassRoomDTO.getRoomNm())
.hdcnt(eclassRoomDTO.getHdcnt())
.useYn(eclassRoomDTO.getUseYn())
.build();
}
/* EclassRoom Insert roomCdId 자동 증가용 */
public static EclassRoomEntity buildNewId(String newRoomCdId, EclassRoomDTO eclassRoomDTO) { // DTO -> Entity 변환
return EclassRoomEntity.builder() // builder을 이용하여 entity 객체 생성
.roomCdId(newRoomCdId)
.roomNm(eclassRoomDTO.getRoomNm())
.hdcnt(eclassRoomDTO.getHdcnt())
.useYn(eclassRoomDTO.getUseYn())
.build();
}
}
(4). Repository 생성
// Entity명 , PK Type
public interface EclassRoomRepository extends JpaRepository<EclassRoomEntity, String> {
}
(4). 전체 조회
1). Controller
@RestController
@RequiredArgsConstructor // final을 가진 생성자 자동 생성
@Tag(name = "Eclass - Room")
public class EclassRoomController {
private final EclassRoomService eclassRoomService; // 생성자 주입 방식
/* @RestController이 적용되면 @ResponseBody를 사용하지 않아도 자동으로 됨 /*
/* Test Class 생성 단축키 : Ctrl + Shift + T */
/* 전체 조회 */
@GetMapping("/selectEclassRoomList")
@Operation(summary = "강의실 리스트", description = "강의실 리스트")
public ResponseEntity<List<EclassRoomDTO>> getAllEclassRooms() {
// Service에서 모든 강의실 정보를 조회하여 List<EclassRoomEntity>로 받아옴
List<EclassRoomEntity> eclassRoomEntityList = eclassRoomService.getAllEclassRooms();
List<EclassRoomDTO> eclassRoomDTOList = eclassRoomEntityList
.stream() // List -> stream()으로 변환
.map(EclassRoomDTO::toDTO) // 각각의 EclassRoomEntity를 EclassRoomDTO로 변환
.collect(Collectors.toList()); // stream() -> List 변환
// 강의실 정보를 ResponseEntity로 감싸서 반환
// 성공 시 200 코드와 정보가 담긴 eclassRoomDTOList가 담긴 ResponseEntity를 반환
return new ResponseEntity<>(eclassRoomDTOList, HttpStatus.OK);
}
}
2). Service
@Service
@RequiredArgsConstructor // final을 가진 생성자 자동 생성
public class EclassRoomService {
private final EclassRoomRepository eclassRoomRepository;
/* Test Class 생성 단축키 : Ctrl + Shift + T */
/* 전체 조회, 단건 조회 = Entity -> DTO 변환
* 등록, 수정 = DTO -> Entity 변환
* 클라이언트 -> DB인지, DB -> 클라이언트인지 생각하면 됨 */
/* 전체 조회 */
public List<EclassRoomEntity> getAllEclassRooms() {
/* Repository에 find.All()을 사용하여 모든 강의실 정보를 DB에서 가져온다.
* 조회된 강의실 정보를 리스트로 반환한다.*/
return eclassRoomRepository.findAll(); // findAll() = 전체 조회
}
}
(5). 단건 조회
1). Controller
@RestController
@RequiredArgsConstructor // final을 가진 생성자 자동 생성
@Tag(name = "Eclass - Room")
public class EclassRoomController {
private final EclassRoomService eclassRoomService; // 생성자 주입 방식
/* @RestController이 적용되면 @ResponseBody를 사용하지 않아도 자동으로 됨 /*
/* Test Class 생성 단축키 : Ctrl + Shift + T */
/* 단건 조회 */
@GetMapping("/selectEclassRoomList/{roomCdCi}")
@Operation(summary = "강의실 단건 조회", description = "강의실 단건 조회")
public ResponseEntity<EclassRoomDTO> getEclassRoom(@PathVariable String roomCdCi) {
// Service에 getEclassRoom(roomCdCi)를 호출하여 단일 정보를 가져오고 DTO에 저장.
// Service에서 Controller로 넘겨줄 때 Entity -> DTO로 변환하여 넘겨줌
EclassRoomDTO eclassRoomDTO = eclassRoomService.getEclassRoom(roomCdCi);
if (eclassRoomDTO == null) { // eclassRoomDTO가 null이면 해당 404 에러 코드 반환
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
} else if (eclassRoomDTO.getRoomCdId() == null) { // roomCdId가 null이면 해당 404 에러 코드 반환
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
} else {
// 성공 시 200 코드와 정보가 담긴 eclassRoomDTO가 담긴 ResponseEntity를 반환
return new ResponseEntity<>(eclassRoomDTO, HttpStatus.OK);
}
}
}
2). Service
@Service
@RequiredArgsConstructor // final을 가진 생성자 자동 생성
public class EclassRoomService {
private final EclassRoomRepository eclassRoomRepository;
/* Test Class 생성 단축키 : Ctrl + Shift + T */
/* 전체 조회, 단건 조회 = Entity -> DTO 변환
* 등록, 수정 = DTO -> Entity 변환
* 클라이언트 -> DB인지, DB -> 클라이언트인지 생각하면 됨 */
/* 단건 조회 */
public EclassRoomDTO getEclassRoom(String roomCdCi) {
// roomCdCi에 맞는 강의실 정보를 가져온다. 해당되는 강의실이 없으면 예외 발생
EclassRoomEntity entity = eclassRoomRepository.findById(roomCdCi) // findById(roomCdCi) = roomCdCi를 이용하여 단건 조회
.orElseThrow(() -> new EntityNotFoundException("roomCdCi not found ! : " + roomCdCi)); // roomCdCi가 없으면 예외
return EclassRoomDTO.toDTO(entity); // entity를 DTO로 변환하여 반환
}
}
(6). 등록
1). Controller
@RestController
@RequiredArgsConstructor // final을 가진 생성자 자동 생성
@Tag(name = "Eclass - Room")
public class EclassRoomController {
private final EclassRoomService eclassRoomService; // 생성자 주입 방식
/* @RestController이 적용되면 @ResponseBody를 사용하지 않아도 자동으로 됨 /*
/* Test Class 생성 단축키 : Ctrl + Shift + T */
/* 등록 */
@PostMapping("/InsertEclassRoom")
@Operation(summary = "강의실 등록", description = "강의실 등록")
public ResponseEntity<EclassRoomDTO> createEclassRoom(@RequestBody EclassRoomDTO eclassRoomDTO) {
/* eclassRoomService.createEclassRoom(eclassRoomDTO)을 호출하여
등록 정보가 담긴 DTO를 사용하여 강의실을 등록하고, 등록된 정보를 createdRoom에 저장 */
EclassRoomDTO createdRoom = eclassRoomService.createEclassRoom(eclassRoomDTO);
// 강의실 정보를 ResponseEntity로 감싸서 반환
return new ResponseEntity<>(createdRoom, HttpStatus.CREATED);
}
}
2). Service
@Service
@RequiredArgsConstructor // final을 가진 생성자 자동 생성
public class EclassRoomService {
private final EclassRoomRepository eclassRoomRepository;
/* Test Class 생성 단축키 : Ctrl + Shift + T */
/* 전체 조회, 단건 조회 = Entity -> DTO 변환
* 등록, 수정 = DTO -> Entity 변환
* 클라이언트 -> DB인지, DB -> 클라이언트인지 생각하면 됨 */
/* 등록 */
public EclassRoomDTO createEclassRoom(EclassRoomDTO eclassRoomDTO) {
// Repository에서 JPQL 가져오기
Integer maxNumericValue = eclassRoomRepository.findMaxNumericValue();
// 현재 roomCdCI이 null이면 초기값으로 0 설정
if (maxNumericValue == null) {
maxNumericValue = 0;
}
// 현재 최대값에서 1을 더하여 새로운 roomCdId 생성 | MA-1 -> MA-2 ...
int newNumericValue = maxNumericValue + 1;
String newRoomCdId = "MA-" + newNumericValue;
// newRoomCdId, DTO를 roomEntity에 담고 저장
EclassRoomEntity roomEntity = EclassRoomEntityBuilder.buildNewId(newRoomCdId, eclassRoomDTO); // 객체 생성
// roomEntity를 DB에 저장하고, 저장된 Entity를 savedEntity에 반환
EclassRoomEntity savedEntity = eclassRoomRepository.save(roomEntity); // save = 엔티티가 있으면 수정, 없으면 등록
return EclassRoomDTO.toDTO(savedEntity); // Entity -> DTO 변환하여 반환
}
}
3). Repository
public interface EclassRoomRepository extends JpaRepository<EclassRoomEntity, String> {
// 등록 시 현재 DB에서 가장 큰 roomCdId SELECT하는 쿼리문
/*
room_cd_id에서 MA-다음 숫자 부분을 추출하고 최대값을 찾는다.
room_cd_id에서 4번째 문자부터 끝까지 문자열을 추출하고 문자열 -> 정수로 변환
nativeQuery = true == JPA 쿼리(JPQL)가 아닌 SQL 쿼리를 사용할 때는 적어줘야됨
service에서도 쿼리를 작성할 수 있지만 가독성을 위해 Repository에 작성함
*/
@Query(value = "SELECT MAX(CAST(SUBSTRING(room_cd_id, 4) AS int)) FROM room_cd", nativeQuery = true)
Integer findMaxNumericValue();
}
(7). 수정
1). Controller
@RestController
@RequiredArgsConstructor // final을 가진 생성자 자동 생성
@Tag(name = "Eclass - Room")
public class EclassRoomController {
private final EclassRoomService eclassRoomService; // 생성자 주입 방식
/* @RestController이 적용되면 @ResponseBody를 사용하지 않아도 자동으로 됨 /*
/* Test Class 생성 단축키 : Ctrl + Shift + T */
/* 수정 */
@PutMapping("/UpdateEclassRoom/{roomCdCi}")
@Operation(summary = "강의실 수정", description = "강의실 정보 수정")
public ResponseEntity<EclassRoomDTO> updateEclassRoom(@PathVariable String roomCdCi, @RequestBody EclassRoomDTO eclassRoomDTO) {
/* eclassRoomService.updateEclassRoom(roomCdCi, eclassRoomDTO)을 호출하여
등록 정보가 담긴 DTO를 사용하여 강의실을 등록하고, 등록된 정보를 updatedRoom에 저장 */
EclassRoomDTO updatedRoom = eclassRoomService.updateEclassRoom(roomCdCi, eclassRoomDTO);
// 강의실 정보를 ResponseEntity로 감싸서 반환
return new ResponseEntity<>(updatedRoom, HttpStatus.OK);
}
}
2). Service
package tuna.tunaEclass.tunaEclass.eclassRoom.service;
import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import tuna.tunaEclass.tunaEclass.eclassRoom.dto.EclassRoomDTO;
import tuna.tunaEclass.tunaEclass.eclassRoom.dto.EclassRoomEntityBuilder;
import tuna.tunaEclass.tunaEclass.eclassRoom.entity.EclassRoomEntity;
import tuna.tunaEclass.tunaEclass.eclassRoom.repository.EclassRoomRepository;
import java.util.List;
@Service
@RequiredArgsConstructor // final을 가진 생성자 자동 생성
public class EclassRoomService {
private final EclassRoomRepository eclassRoomRepository;
/* Test Class 생성 단축키 : Ctrl + Shift + T */
/* 전체 조회, 단건 조회 = Entity -> DTO 변환
* 등록, 수정 = DTO -> Entity 변환
* 클라이언트 -> DB인지, DB -> 클라이언트인지 생각하면 됨 */
/* 수정 */
public EclassRoomDTO updateEclassRoom(String roomCdCi, EclassRoomDTO eclassRoomDTO) {
/* 강의실 코드로 강의실을 조회한다, 해당 코드가 없으면 예외 발생 */
EclassRoomEntity existingEntity = eclassRoomRepository.findById(roomCdCi)
.orElseThrow(() -> new EntityNotFoundException("roomCdCi not found ! : " + roomCdCi));
// DTO를 Entity로 변환
EclassRoomEntity updatedEntity = EclassRoomEntityBuilder.buildFromDTO(eclassRoomDTO);
// Entity 식별자를 설정
updatedEntity.setRoomCdId(existingEntity.getRoomCdId());
// 수정된 Entity를 DB에 저장하고, updatedEntity에 다시 할당
updatedEntity = eclassRoomRepository.save(updatedEntity);
return EclassRoomDTO.toDTO(updatedEntity); // Entity -> DTO 변환하여 반환
}
}
(8). 삭제
1). Controller
@CrossOrigin("*")
@RestController
@RequiredArgsConstructor // final을 가진 생성자 자동 생성
@Tag(name = "Eclass - Room")
public class EclassRoomController {
private final EclassRoomService eclassRoomService; // 생성자 주입 방식
/* @RestController이 적용되면 @ResponseBody를 사용하지 않아도 자동으로 됨 /*
/* Test Class 생성 단축키 : Ctrl + Shift + T */
/* 삭제 */
@DeleteMapping("/DeleteEclassRoom/{roomCdCi}")
@Operation(summary = "강의실 삭제", description = "강의실 삭제")
// Void를 사용한 이유 = 해당 메서드가 반환하는데 반환할 데이터가 없음을 나타내기 위해
public ResponseEntity<Void> deleteEclassRoom(@PathVariable String roomCdCi) {
/* eclassRoomService.deleteEclassRoom(roomCdCi)를 호출하여
해당되는 roomCdCi를 포함하는 강의실을 삭제합니다 */
eclassRoomService.deleteEclassRoom(roomCdCi);
return ResponseEntity.noContent().build();
}
}
2). Service
@Service
@RequiredArgsConstructor // final을 가진 생성자 자동 생성
public class EclassRoomService {
private final EclassRoomRepository eclassRoomRepository;
/* Test Class 생성 단축키 : Ctrl + Shift + T */
/* 전체 조회, 단건 조회 = Entity -> DTO 변환
* 등록, 수정 = DTO -> Entity 변환
* 클라이언트 -> DB인지, DB -> 클라이언트인지 생각하면 됨 */
/* 삭제 */
public void deleteEclassRoom(String roomCdCi) {
/* 강의실 코드로 강의실을 조회한다, 해당 코드가 없으면 예외 발생 */
EclassRoomEntity existingEntity = eclassRoomRepository.findById(roomCdCi) // findById(roomCdCi) = roomCdCi를 이용하여 조회
.orElseThrow(() -> new EntityNotFoundException("roomCdCi not found ! : " + roomCdCi)); // roomCdCi가 없으면 예외
// 엔터티 삭제
eclassRoomRepository.delete(existingEntity); // .delete = 삭제
}
}
4. Swagger 확인
5. PostMan을 이용하여 테스트
'Java > Spring Boot' 카테고리의 다른 글
[MSA] Spring Cloud로 MSA를 개발해보자 5편 [Config] (0) | 2024.08.26 |
---|---|
[MSA] Spring Cloud로 MSA를 개발해보자 4편 [JWT 인증] (0) | 2024.08.25 |
[MSA] Spring Cloud로 MSA를 개발해보자 3편 [Gateway Service-2] (0) | 2024.08.16 |
[MSA] Spring Cloud로 MSA를 개발해보자 2편 [Gateway Service] (1) | 2024.08.13 |
[MSA] Spring Cloud로 MSA를 개발해보자 1편 [Service Discovery] (0) | 2024.08.11 |