본문 바로가기
Spring/SpringBoot

[SpringBoot] 호텔예약사이트 - 관리자 객실 등록

by 코딩맛 2024. 3. 30.
해당 글은 Spring으로 구현한 프로젝트를 SpringBoot로 리팩토링 하는 과정을 담은 글입니다.

 

이번 시간에는 관리자 기능 중 하나인 객실 정보를 등록하는 작업을 하려고 합니다.

 

기능 순서

1. 객실 목록 페이지에서 등록 버튼 클릭 시 등록페이지 이동

2. 등록페이지에서 객실 정보 및 이미지 등록 후 객실 목록 페이지로 이동

 

1. Controller - roomInsertPage() 메서드  선언

- 객실 목록 페이지에서 등록 버튼을 클릭했을 때 이동하는 매핑 URL과 메서드를 선언

@GetMapping("/admin/roomInsertPage")
public String roomInsertPage() throws Exception {
    return "admin/roomInsert";
}

 

2. view 선언

<div id="table">
        <table style="margin:auto;">
            <caption style="visibility:hidden">객실등록 테이블</caption>
            <colgroup>
                <col style="width: 20%;">
                <col style="width: 30%;">
                <col style="width: 20%;">
                <col style="width: 30%;">
            </colgroup>
            <tbody>
            <tr>
                <th><span id="vali">*</span>객실명</th>
                <td colspan="3"><input type="text" id="roomName" name="roomName" /></td>
            </tr>
            <tr>
                <th><span id="vali">*</span>객실요금</th>
                <td><input type="text" id="roomPrice" name="roomPrice" />&nbsp;원</td>
                <th><span id="vali">*</span>객실수</th>
                <td><input type="number" id="roomAmount" name="roomAmount" /></td>
            </tr>
            <tr>
                <th><span id="vali">*</span>객실크기</th>
                <td><input type="number" id="roomSize" name="roomSize" step="0.01" />&nbsp;㎡</td>
                <th><span id="vali">*</span>최대인원수</th>
                <td><input type="number" id="peopleNum" name="peopleNum" /></td>
            <tr>
                <th><span id="vali">*</span>침대타입</th>
                <td colspan="3"><input type="text" id="bedType" name="bedType" /></td>
            </tr>
            <tr>
                <th>특이사항</th>
                <td colspan="3"><textarea id="roomSpec" name="roomSpec"></textarea></td>
            </tr>
            <tr>
                <th>첨부파일</th>
                <td colspan="3">
                    <div id="fileList">
                        <div>
                            <!-- inline은 붙여서, inline-block은 블록 형태, 약간 여백 있음 -->
                            <input type="file" name="file" style="display: inline-block;" accept="">
                        </div>
                    </div>
                </td>
            </tr>
            </tbody>
        </table>
        <div class="btn">
            <button type="button" onclick="insert();">등록</button>
            <button type="button" onclick="location.href='/admin/roomList'">목록</button>
        </div>
    </div>

등록 버튼을 눌러 insert() 함수 호출

객실 등록페이지 화면

3. js 선언

function insert(){
	var frm = document.insertForm;

	if(frm.roomName.value == ""){
		alert("객실명을 입력하세요.");
		return false;
	}

	if(frm.roomPrice.value == ""){
        alert("객실요금을 입력하세요.");
        return false;
    }

    if(frm.roomAmount.value == ""){
        alert("객실수를 입력하세요.");
        return false;
    }

    if(frm.roomSize.value == ""){
        alert("객실크기를 입력하세요.");
        return false;
    }

    if(frm.peopleNum.value == ""){
        alert("최대인원수를 입력하세요.");
        return false;
    }

    if(frm.bedType.value == ""){
        alert("침대타입을 입력하세요.");
        return false;
    }

	frm.submit();
}

js에서 validation 체크를 해주고 form의 action값에 들어있는 주소로 전송.

 

4. Controller - roomInsert() 메서드  선언

@PostMapping("/admin/roomInsert")
public String roomInsert(Room room, RoomImage roomImage, MultipartFile file, Model model) throws Exception {

    roomImage.setRoom(room);
    sonorousRoomService.insert(roomImage, file);

    model.addAttribute("message", "글 작성이 완료되었습니다.");
    model.addAttribute("searchUrl","/admin/roomList");

    return "common/writeMessage";
}

room 엔티티와 roomImage 엔티티를 따로 받은 뒤,

roomImage 엔티티의 room 필드에 room엔티티 값을 담아줌

서비스의 .insert() 메서드를 호출하는데 인자값으로 roomImage와 file을 전달.

 

5. Service - insert() 메서드 선언

public void insert(RoomImage roomImage, MultipartFile file) throws Exception{
    String projectPath = System.getProperty("user.dir") + "/src/main/resources/static/files";

    UUID uuid = UUID.randomUUID();

    String fileName = uuid + "_" + file.getOriginalFilename();

    File saveFile = new File(projectPath, fileName);

    file.transferTo(saveFile);

    roomImage.setRoomImageName(fileName);
    roomImage.setRoomImagePath("/files/" + fileName);

    sonorousRoomRepository.save(roomImage);
}

1. 파일을 프로젝트 내에 생성

 - projectPath : 파일을 생성할 디렉토리 경로를 선언.

 - uuid : 랜덤값 생성

 - saveFile : 파일 객체 생성

 - .transferTo() : 파일 전송

 

2. DB에 파일 정보 저장

 

DB에 저장 후 객실 목록 페이지로 이동.

 


여기까지만 진행하면 데이터 등록, 수정 시간이 들어가지 않음.

 

이어서 진행할 것은 JPA Auditing을 이용해 자동으로 생성/수정 시간을 넣어주려고 함.

 

1. BaseTimeEntity 클래스 작성

@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseTimeEntity {

    @CreatedDate
    private LocalDateTime createdDate;

    @LastModifiedDate
    private LocalDateTime modifiedDate;
}

 

- @MapppedSuperClass : JPA Entity 클래스들이 해당 어노테이션이 붙은 클래스를 상속한 경우 해당 클래스의 필드를 컬럼으로 인식

- @EntityListeners(AuditingEntityListener.class) : 해당 어노테이션이 붙은 클래스에 Auditing 기능을 포함

- @CreatedDate : Entity가 생성되어 저장될 때 시간이 자동 저장

- @LastModifiedDate : 조회한 Entity의 값을 변경할 때 시간이 자동 저장

 

2. entity에 상속하기

public class Room extends BaseTimeEntity{

 

생성시간과 수정시간을 room entity 클래스에 BaseTimeEntity 클래스를 상속.

 

3. JPA Auditing 기능 활성화

@EnableJpaAuditing
@SpringBootApplication
public class SonorousApplication {

	public static void main(String[] args) {

		SpringApplication.run(SonorousApplication.class, args);
	}

}

Main 함수가 있는 클래스에 @EnableJpaAuditing 어노테이션 선언.

 

다시 객실을 등록하면 

 

created_date와 modified_date 컬럼에 날짜와 시간이 들어간 것을 확인할 수 있음.

 

 

참고 블로그

https://velog.io/@ovan/JPA-Auditing%EC%9C%BC%EB%A1%9C-%EC%83%9D%EC%84%B1%EC%8B%9C%EA%B0%84%EC%88%98%EC%A0%95%EC%8B%9C%EA%B0%84-%EC%9E%90%EB%8F%99%ED%99%94%ED%95%98%EA%B8%B0

 

JPA Auditing으로 생성시간/수정시간 자동화하기

OVERVIEW 이번 포스팅에서는 JPA Auditing이라는 것을 이용하여 생성시간, 수정시간 생성을 자동화 하는 방법에 대해 알아본다. 전통적인 방법 DB에 데이터를 삽입할 때 보통 생성시간과 수정시간을

velog.io