본문 바로가기
Spring/SpringBoot

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

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

 

이번 시간에는 관리자로 로그인하여 객실 정보를 불러오는 작업을 하려고 합니다.

 

1. 테이블 구조

테이블은 room, room_image으로 구성되어 있습니다.

ROOM 테이블
ROOM_IMAGE 테이블

 

객실 정보를 불러올 때 객실 이미지 정보도 같이 불러와서 목록에 노출시켜야 하므로

객실테이블과 객실 이미지 테이블을 조인 시켜줘야 합니다.

 

2. Entity 선언

 

** 객실 테이블, 객실 이미지 테이블 관계 **

- 객실 테이블 : 주 테이블

- 객실 이미지 테이블 : 대상 테이블

 

객실과 객실이미지는 양방향 관계가 되는데 객실이미지 테이블에 외래키 설정이 되어 있다.

이 구조는 외래키에 Null 값이 들어가지 않는다. 객실이미지는 객실이 없으면 존재하지 않는다.

 

1) Room.java (객실엔티티 - 주 테이블)

package com.boot.sonorous.admin.entity;

import jakarta.persistence.*;
import lombok.Data;
import lombok.ToString;

@Entity
@Data
@ToString(exclude = "roomImage")
@Table(name = "T_ROOM")
public class Room {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ROOM_ID")
    private int Id;

    private String roomName;
    private String roomSize;
    private String bedType;
    private String roomPrice;
    private String roomAmount;
    private String peopleNum;
    private String roomSpec;
    private String insId;
    private String insDate;
    private String modId;
    private String modDate;

    @OneToOne(mappedBy = "room")
    private RoomImage roomImage;
}

 

2) RoomImage.java

@Entity
@Data
@Table(name = "T_ROOM_IMAGE")
public class RoomImage {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ROOM_IMAGE_ID")
    private int Id;

    private String roomImageName;
    private String roomImagePath;

    @OneToOne
    @JoinColumn(name="room_id")
    private Room room;
}

대상테이블에 외래키를 둬야하기 때문에 @JoinColmn을 객실이미지엔티티에 둡니다.

Room 엔티티에 RoomImage 필드에 mappedBy 속성을 통해 연관 관계의 주인이 RoomImage에 있음을 알립니다.

 

3. Controller 선언

@Controller
public class SonorousRoomController {

    @Autowired
    private SonorousRoomService sonorousRoomService;

    @GetMapping("/roomList")
    public String roomList(Model model, HttpSession session, HttpServletResponse response) throws Exception {
        // 1. 세션값이 널이거나
        // 2. 관리자 권한이 아니면 로그인 페이지 이동
        Member loginMember = (Member)session.getAttribute("loginMember");
        if(loginMember == null || !(loginMember.getMAuth().equals("ADMIN"))){
            response.setContentType("text/html; charset=UTF-8");
            PrintWriter out = response.getWriter();
            out.println("<script>alert('접근 권한이 없습니다.');</script>");
            out.flush();
            out.close();
        }
        List<RoomImage> roomList = sonorousRoomService.roomList();
        System.out.print(roomList);
        model.addAttribute("roomList", roomList);

        return "admin/roomList";
    }
}

 

서비스에 객실 정보를 불러오는 roomList() 메서드를 호출, 엔티티 타입이 RoomImage인 List에 담습니다.

 

4. service 선언

@Service
public class SonorousRoomService {
    @Autowired
    SonorousRoomRepository sonorousRoomRepository;

    public List<RoomImage> roomList() {
        return sonorousRoomRepository.findAll();
    }
}

레퍼지토리에 테이블 모든 컬럼을 조회하는 findAll() 메서드를 호출, List<RoomImage>로 반환합니다.

 

5. Repository 선언

@Repository
public interface SonorousRoomRepository extends JpaRepository<RoomImage, Integer> {
}

레퍼지토리 인자에 RoomImage 엔티티와 Id 값의 타입인 Integer를 넣습니다.

controller에서 roomList 이름의 리스트에 담고 admin/roomLIst 경로의 view 호출합니다.

 

6. view 선언

<div id="table">
                <table style="margin:auto; text-align:center;">
                    <caption style="visibility:hidden">카테고리ID, 케테고리명, 사용여부, Description, 등록자 표시하는 테이블</caption>
                    <colgroup>
                        <col width="10%"/>
                        <col width="30%"/>
                        <col width="40%"/>
                        <col width="20%"/>
                    </colgroup>
                    <tr>
                        <th align="center">No</th>
                        <th align="center">이미지</th>
                        <th align="center">객실이름</th>
                        <th align="center">등록일</th>
                    </tr>
                    <tr th:each="room : ${roomList}">
                        <td th:text="${room.room.Id}"></td>
                        <td th:if="${room.roomImageName != null}">
                            <img style="width: 150px;height:100px" th:src="'/upload/' + ${room.roomImagePath} + '/' + ${room.roomImageName}"/></td>
                        <td>
                            <a th:href="'/roomView?Id=' + ${room.room.Id}" th:text="${room.room.roomName}"></a>
                        </td>
                        <td th:text="${room.room.insDate}"></td>
                    </tr>
                </table>
            </div>

 

roomList 리스트에 담긴 값을 room에 하나씩 담고 값을 꺼내옵니다.

room(객실 이미지정보) > room(객실 정보)가 있으므로 객실 id를 가져오려면 room.room.Id로 가져와줍니다.

객실 이미지는 /upload/객실이미지경로/객실이미지이름 경로에 있어

src에 위와 같이 작성하면 이미지를 불러옵니다.

 

객실 목록 페이지 화면

참고블로그

https://wildeveloperetrain.tistory.com/186

 

JPA @OneToOne 일대일 연관 관계 정리 및 LazyLoding 이슈

JPA를 사용하면서도 연관 관계 매핑을 쓰지 않다가 이번 프로젝트에서 연관 관계를 적용하기 시작하며 정리한 내용이며, JPA 연관 관계 매핑 중에서 1:1 연관 관계인 @OneToOne에 대해 정리한 내용입

wildeveloperetrain.tistory.com