스프링 프레임워크/쇼핑몰 프로젝트

[Spring][쇼핑몰 프로젝트][50] 상품 테이블 평균 평점 반영

Kim VamPa 2022. 1. 20. 10:00
728x90
반응형
프로젝트 Github : https://github.com/sjinjin7/Blog_Project
프로젝트 포스팅 색인(index) : https://kimvampa.tistory.com/188

 

목표

상품 테이블 평점 적용

 vam_book테이블에 ratingAvg컬럼을 추가하고 댓글 '등록', '수정', '삭제'할 때 해당 상품의 평균 평점 값이 최신화되도록 기능을 구현할 것입니다.

 

 

순서

1. 개요

2. 컬럼추가

3. DTO

4. Mapper

5. Service

6. 테스트

7. 보완

 

 

 

1. 개요

 vam_book 테이블에 ratingAvg컬럼을 추가해 줄 것입니다. 이 컬럼의 목적은 해당 상품 평점의 평균 값이 저장되도록 하는 것이 목적입니다. 이번 포스팅에선 이 컬럼의 값이 댓글 등록, 수정, 삭제될 때마다 평점의 평균값을 구해서 값이 최신화 되도록 하는 것이 목표입니다. 

 

 구현을 위해서 Service 단계에서 댓글의 등록, 수정, 삭제 될때마다 상품의 평점 평균을 구하고 그 값을 해당 상품 테이블(vam_book)의 ratingAvg컬럼 값으로 최신화하도록 만들 것입니다. 먼저 평점의 평균을 구하는 Mapper 메서드, 구한 평균값을 vam_book 테이블에 반영하는 Mapper 메서드를 만들겠습니다.

 

※ 등록, 수정, 삭제 순간마다 평균 평점을 구하고, DB에 반영 하는 것은 매우 많은 요청이 있을 시 서버의 자원을 많이 잡아먹는 요인이 될 수 있다고 생각됩니다. 따라서 배치 프로그램을 사용해서 특정 시간마다 평점을 최신화하는 코드가 동작하도록 하는 방법도 있을 거 같습니다.

 

2. 컬럼추가

 DB에서 아래의 쿼리 명령어를 실행해서 rating 컬럼을 추가합니다.

 

Oracle

 

alter table vam_book add ratingAvg number(2,1);

 

 

MySQL

 

alter table vam_book add ratingAvg decimal(2,1);

 

 

 

3. DTO

 평점 평균값을 vam_book 테이블의 ratingAvg에 반영할때 실행될 쿼리에는 '반영 할 평점 평균 값'과 어떠한 상품 평균 값을 구할지에 대한 조건인 '상품 번호(bookId)'가 필요로 합니다. 따라서 평균값 반영 쿼리를 실행 할 Mapper 메서드에 두개의 데이터를 한번에 전달 할 수 있도록 DTO클래스를 새로 작성 해주고자 합니다.

 

 com.vam.model 패키지에 UpdateReplyDTO 클래스를 생성합니다.

 

그림 3-1

 

 

상품의 평균값을 저장 할 수 있는 double 타입의 변수와 상품번호 값을 저장 할 수 있는 int타입의 변수를 선언합니다.

 

	private int bookId;
	
	private double ratingAvg;

 

그림 3-2

 

 

 선언 한 변수에 대한 getter/setter/toString 메서드를 작성해줍니다.

 

그림 3-3

 

 

4. Mapper 메서드

 

ReplyMapper 인터페이스

 

 com.vam.mapper 패키지의 Mapper 메서드에 특정 상품의 평점 평균 값을 구하는 메서드와 구한 평점 평균 값을 vam_book 테이블의 rating 컬럼에 반영하는 메서들 작성합니다.

 

* getReplyAverage

 - 어떠한 상품의 평점 평균값인지 조건을 주기 위해 int 타입의 bookId 변수를 파라미터로 선언했습니다.

 - 평점 평균값을 반환받을 수 있도록 Double 타입을 반환 타입으로 지정 했습니다. (아직 상품 평점이 없어서 null을 반환 할 수도 있다고 생각되어 double 기본 타입이 아닌 null또한 값으로 가질 수 있는 Wrapper 클래스인 Double을 반환타입으로 지정했습니다.)

 

* updateRating

  - '상품번호', '평균 평점 값'을 전달받을 수 있도록 파라미터로 UpdateReplyDTO 타입의 변수를 선언했습니다.

 

	/* 평점 평균 구하기 */
	public Double getRatingAverage(int bookId);
	
	/* 평점 평균 반영하기 */
	public int updateRating(UpdateReplyDTO dto);

 

그림 4-1

 

 

 ReplyMapper.xml

 

  src/main/resources/com/vam/mapper 경로에 있는 ReplyMapper.xml 파일에 인터페이스에서 선언한 메서드가 수행할 쿼리문을 작성합니다.

 

   	<select id="getRatingAverage" resultType="double">
  	
  		select avg(rating)
  		from vam_reply
  		where bookId = #{bookId}
  	
  	</select>

	<update id="updateRating">
	
		update vam_book
		set ratingAvg = #{ratingAvg}
		where bookId = #{bookId}
	
	</update>

 

그림 4-2

 

 

5. Service

 

 댓글 등록, 수정, 삭제 Service 메서드에 평균 평점을 반영해주는 코드를 추가해주어야 하는데 3 가지 모두 동일한 코드를 사용할 것이기 때문에 단순히 메서드를 호출만 할 수 있도록, 메서드를 만들어주겠습니다.

 

 com.vam.service 패키지의 ReplyServiceImpl클래스에 setRating 메서드를 선언합니다.

 

 - 반환 타입은 없습니다.

 -  상품 번호 값이 필요로 하기 때문에 int 타입의 bookId를 파라미터 변수로 선언했습니다.

 

	public void setRating(int bookId) {
		
	}

 

그림 5-1

 

 

 선언한 메서드의 구현부에 먼저 상품의 평점 평균값을 구하는 Mapper 메서드를 호출하여 반환받은 값을 새로 선언한 변수에 대입하는 코드를 작성합니다.

 

	public void setRating(int bookId) {
		
		Double ratingAvg = replyMapper.getRatingAverage(bookId);		
		
	}

 

 

 반환 받은 값이 null 일 경우 변수에 0이 저장되도록 if문을 사용해서 작성했습니다.

 

	public void setRating(int bookId) {
		
		Double ratingAvg = replyMapper.getRatingAverage(bookId);	
		
		if(ratingAvg == null) {
			ratingAvg = 0.0;
		}		
		
	}

 

 

 UpdateReplyDTO 객체를 인스턴스화 하여 bookId, ratingAvg 값을 객체의 변수에 저장합니다.

 

	public void setRating(int bookId) {
		
		Double ratingAvg = replyMapper.getRatingAverage(bookId);	
		
		if(ratingAvg == null) {
			ratingAvg = 0.0;
		}	
		
		UpdateReplyDTO urd = new UpdateReplyDTO();
		urd.setBookId(bookId);
		urd.setRatingAvg(ratingAvg);		
		
	}

 

 

 값이 세팅된 UpdateReplyDTO 객체를 인자로 하는 updateRating Mapper 메서드(테이블에 평균 평점 반영)를 호출합니다.

 

	public void setRating(int bookId) {
		
		Double ratingAvg = replyMapper.getRatingAverage(bookId);	
		
		if(ratingAvg == null) {
			ratingAvg = 0.0;
		}	
		
		UpdateReplyDTO urd = new UpdateReplyDTO();
		urd.setBookId(bookId);
		urd.setRatingAvg(ratingAvg);	
		
		replyMapper.updateRating(urd);		
		
	}

 

그림 5-2

 

 

 이로써 상품의 평균값을 구하고 vam_book테이블 ratingAvg 컬럼에 값을 반영하는 메서드를 완성했습니다. 작성한 메서드를 등록, 수정, 삭제 Service 메서드 구현부에서 호출해줍니다.

 

등록

 

그림 5-3

 

 

수정

 

그림 5-4

 

 

삭제

 

그림 5-5

 

 

6. 테스트

 상품을 등록, 수정, 삭제했을때 해당 상품의 평균 평점 값이 변경되었는지 확인해봅니다. 테스트를 위해서 vam_reply테이블에 한 상품에 대한 행을 여러 개 추가했습니다.

 

그림 6-1

 

 

 댓글 등록, 수정, 삭제 후 vam_book의 ratingAvg에 값이 반영이 되었는지 확인합니다.

 

ㅡ림 6-2

 

 

 값이 들어왔는데 소수점 아래 너무 많은 값이 들어와 있는 걸 확인했습니다. 이를 소수점 첫째 자리까지 표시가 되도록 보완해보겠습니다.

 

 

7. 보완

 평균값의 소수점 첫째 자리까지 표시하기 위해서 DB단계에서 가공을 하거나 Java에서 가공을 할 수 있습니다. 전 Java에서 Math 클래스의 round 함수를 사용하여 가공을 하겠습니다. 

 

 ReplyServiceImpl에 작성했던 setRating 구현부에서 if문 다음 공간에 아래의 코드를 추가해줍니다.

 

		ratingAvg = (double) (Math.round(ratingAvg*10));
		ratingAvg = ratingAvg / 10

 

그림 7-1

 

 

 서버를 구동하여 댓글 등록, 수정, 삭제 중 하나를 수행하여 값이 제대로 들어오는지 확인합니다.

 

그림 7-2

 

 

REFERENCE

  •  

 

 

DATE

  • 2020.01.20

 

728x90
반응형