😎 STS3 Spring 쇼핑몰

STS3 쇼핑몰 프로젝트[17] 상품 등록 - 등록 기본 구현

개발자 린다씨 2022. 8. 3. 19:06
반응형

순서

1. SwanVO 생성
2. Mapper 작업
3. Service 작업
4. Controller
5. View 작업
6. 테스트

1. SwanVO 생성

'상품 테이블(PRODUCT)' 테이블의 데이터들을 한 번에 전달받거나 전달하기 위해 사용될 클래스를 만듭니다.

 

com.swan.model에 "SwanVO.java" 클래스를 생성합니다.

PRODUCT 테이블의 칼럼들을 변수로 선언해줍니다.

더보기
/* 상품 id */
	private int product_id;
	
	/* 상품 명 */
	private String product_title;
	
	/* 상품 설명 */
	private String product_content;
	
	/* 상품 가격 */
	private int product_price;
	
	/* 상품 수량 */
	private int product_stock;
	
	/* 상품 조회수 */
	private int product_count;
	
	/* 대카테고리 */
	private String kind_id;
	
	private String kind_name;
	
	/* 상품 생성 날짜 */
	private Date product_create_date;
	
	/* 상품 수정 날짜 */
	private Date product_modify_date;
	
	/* 상품 상태 */
	private String product_status;
	
	/* 상품 평점 */
	private double ratingavg;

작성한 변수들의 기본 생성자와 getter/setter/toString 메서드를 생성해줍니다.

더보기
package com.swan.model;

import java.sql.Date;
import java.util.List;

public class SwanVO {
	/* 상품 id */
	private int product_id;
	
	/* 상품 명 */
	private String product_title;
	
	/* 상품 설명 */
	private String product_content;
	
	/* 상품 가격 */
	private int product_price;
	
	/* 상품 수량 */
	private int product_stock;
	
	/* 상품 조회수 */
	private int product_count;
	
	/* 대카테고리 */
	private String kind_id;
	
	private String kind_name;
	
	/* 상품 생성 날짜 */
	private Date product_create_date;
	
	/* 상품 수정 날짜 */
	private Date product_modify_date;
	
	/* 상품 상태 */
	private String product_status;
	
	/* 상품 평점 */
	private double ratingavg;	
	
	public SwanVO() {}

	public SwanVO(int product_id, String product_title, String product_content, int product_price, int product_stock,
			int product_count, String kind_id, String kind_name, Date product_create_date, Date product_modify_date,
			String product_status, double ratingavg) {
		super();
		this.product_id = product_id;
		this.product_title = product_title;
		this.product_content = product_content;
		this.product_price = product_price;
		this.product_stock = product_stock;
		this.product_count = product_count;
		this.kind_id = kind_id;
		this.kind_name = kind_name;
		this.product_create_date = product_create_date;
		this.product_modify_date = product_modify_date;
		this.product_status = product_status;
		this.ratingavg = ratingavg;
	}

	public int getProduct_id() {
		return product_id;
	}

	public void setProduct_id(int product_id) {
		this.product_id = product_id;
	}

	public String getProduct_title() {
		return product_title;
	}

	public void setProduct_title(String product_title) {
		this.product_title = product_title;
	}

	public String getProduct_content() {
		return product_content;
	}

	public void setProduct_content(String product_content) {
		this.product_content = product_content;
	}

	public int getProduct_price() {
		return product_price;
	}

	public void setProduct_price(int product_price) {
		this.product_price = product_price;
	}

	public int getProduct_stock() {
		return product_stock;
	}

	public void setProduct_stock(int product_stock) {
		this.product_stock = product_stock;
	}

	public int getProduct_count() {
		return product_count;
	}

	public void setProduct_count(int product_count) {
		this.product_count = product_count;
	}

	public String getKind_id() {
		return kind_id;
	}

	public void setKind_id(String kind_id) {
		this.kind_id = kind_id;
	}

	public String getKind_name() {
		return kind_name;
	}

	public void setKind_name(String kind_name) {
		this.kind_name = kind_name;
	}

	public Date getProduct_create_date() {
		return product_create_date;
	}

	public void setProduct_create_date(Date product_create_date) {
		this.product_create_date = product_create_date;
	}

	public Date getProduct_modify_date() {
		return product_modify_date;
	}

	public void setProduct_modify_date(Date product_modify_date) {
		this.product_modify_date = product_modify_date;
	}

	public String getProduct_status() {
		return product_status;
	}

	public void setProduct_status(String product_status) {
		this.product_status = product_status;
	}

	public double getRatingavg() {
		return ratingavg;
	}

	public void setRatingavg(double ratingavg) {
		this.ratingavg = ratingavg;
	}

	@Override
	public String toString() {
		return "SwanVO [product_id=" + product_id + ", product_title=" + product_title + ", product_content="
				+ product_content + ", product_price=" + product_price + ", product_stock=" + product_stock
				+ ", product_count=" + product_count + ", kind_id=" + kind_id + ", kind_name=" + kind_name
				+ ", product_create_date=" + product_create_date + ", product_modify_date=" + product_modify_date
				+ ", product_status=" + product_status + ratingavg=" + ratingavg + "]";
	}


}

2. Mapper 작업

AdminMapper.java

상품 등록 쿼리를 실행할 Mapper 메서드를 작성해야 합니다.

먼저 com.swan.mapper 패키지에 "AdminMapper.java" 인터페이스를 생성한 뒤 아래의 메서드를 작성합니다. (사용자가 입력한 데이터를 전달받아야 하기 때문에 SwanVO를 파라미터로 부여하였습니다.)

/* 상품 등록 */
public void swanEnroll(SwanVO swan);

AdminMapper.xml

Config 파일 등록

Window → Preferences type filter text에 xml 검색   XML Catalog User Specified Entries → Add 클릭

Location: http://mybatis.org/dtd/mybatis-3-config.dtd

Key: -//mybatis.org//DTD Config 3.0//EN

OK 클릭

Mapper 등록

Window → Preferences  type filter text에 xml 검색   XML Catalog  User Specified Entries  Add 클릭

Location: http://mybatis.org/dtd/mybatis-3-mapper.dtd

Key: -//mybatis.org//DTD Mapper 3.0//EN

OK 클릭

 

위의 세팅이 완료되었다면 mapper.xml파일이 모여있는 경로에 AdminMapper.xml 파일을 생성합니다.

File name에 AdminMapper 넣고 Next > 클릭합니다.

Create XML file from DTD file을 선택하고 Next >를 클릭합니다.

Select XML Catalog entry를 선택하면 아래에 등록했던 DTD Mapper가 보입니다. DTD Mapper를 선택하고 Next >를 클릭합니다.

Finish를 클릭합니다.

 

이런식으로 Mapper를 등록하면 mybatis를 사용할 수 있도록 해주는 기본적인 태그 코드들을 일일이 적지 않아도 됩니다.

 

AdminMapper.xml을 생성 후 mapper namespace에 아래 코드를 추가합니다.

namespace="com.swan.mapper.AdminMapper"

 AdminMapper.java에서 선언한 메서드가 실행해야할 쿼리 코드를 작성합니다. 

<!-- 상품 등록 -->
	<insert id="swanEnroll">
	<!-- order 속성값 AFTER로 인해서 본 쿼리문(INSERT)이 실행이 된 뒤에 <selectkey> 태그 내의 쿼리문이 실행이 되며, 
	product테이블의 'product_id'값 중 가장 큰 값을 SwanVO에 있는 product_id 변수에 반환시킨다 -->
	<selectKey resultType="_int" keyProperty="product_id" order="AFTER">
  		SELECT MAX(product_id) from product
  	</selectKey>
		insert into product
		values(seq_pid.nextval, #{product_title}, #{product_content}, #{product_price}, #{product_stock},
		default, #{kind_id}, sysdate, sysdate, default, default)
	</insert>

AdminMapperTests.java

 src/test/java 경로에 있는 com.swan.mapper 패키지에 "AdminMapperTests.java" 클래스를 생성 후 Junit 테스트를 할 수 있도록 기본적인 코드들을 추가합니다.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")

아래의 코드를 추가 후 상품 등록 메서드가 정상적으로 동작하는지 Junit 테스트를 합니다.

@Autowired
	private AdminMapper mapper;
	
	/* 상품 등록 */
	@Test
	public void swanEnrollTest() throws Exception{
		
		SwanVO swan = new SwanVO();
		
		swan.setProduct_id(61);
		swan.setProduct_title("mapper 테스트");
		swan.setProduct_content("야홍");
		swan.setProduct_price(70000);
		swan.setProduct_stock(20);
		swan.setKind_id("100000");

		
		System.out.println("Before SwanVO : " + swan);
		mapper.swanEnroll(swan);
		System.out.println("After SwanVO : " + swan);
	}

3. Service 작업

AdminService.java

com.swan.service 패키지에 "AdminService.java" 인터페이스를 생성합니다.

 '상품 등록' mapper 메서드를 호출할 메서드를 작성합니다.

/* 상품 등록 */
public void swanEnroll(SwanVO swan);

AdminServiceImpl.java

com.swan.service 패키지에 "AdminServiceImpl.java" 클래스를 생성합니다.

"AdminService"를 상속받도록 implements 키워드를 추가해주고, log 메서드를 사용하기 위해 @log4j를 선언해주었습니다(Lombok 사용자가 아닐 경우 Logger 클래스를 선언 및 초기화하여 사용하시면 됩니다). 

 

더불어 가장 중요한 @Service 어노테이션을 작성해줍니다.

스프링이 해당 클래스가 Service 역할을 하는 클래스로 인식할 수 있도록 하기 위함입니다.

먼저 AdminMapper 인터페이스를 의존성 주입 해준 후, AdminService.java 에서 선언한 메서드를 오버 라이딩하여 구현합니다.

@Autowired
private AdminMapper adminMapper;	
	
/* 상품 등록 */
@Override
public void swanEnroll(SwanVO swan) {
		
	log.info("(service)swanEnroll........");
		
	adminMapper.swanEnroll(swan);
		
}

4. Controller 작업

 AdminService의 메서드를 사용할 수 있도록 의존성 주입을 해줍니다.

@Autowired
private AdminService adminService;

 AdminController.java 에 '상품 등록'을 수행하는 url 매핑 메서드를 작성합니다.

/* 상품 등록 */
	@Transactional
	@PostMapping("/insertProduct")
	public String productsEnrollPOST(SwanVO swan, RedirectAttributes rttr) {

		logger.info("productsEnrollPOST......" + swan);

		adminService.swanEnroll(swan);

		rttr.addFlashAttribute("enroll_result", swan.getProduct_title());

		return "redirect:/admin/admin";
	}

상품 등록을 수행 후 "상품 관리(admin.jsp)"페이지로 리다이렉트 하여 이동하도록 리턴 값을 작성하였습니다.

 

상품 등록이 완료되었음을 사용자에게 피드백하기 위해 상품 등록 후 '상품 관리 페이지'에 이동하였을 때 등록한 상품 이름과 함께 상품이 등록되었음을 알리는 경고창을 뜨도록 했습니다.

 

이를 위해RedirectAttribute의 addFlashAttribute 메서드를 활용하여 등록한 상품 명을 "enroll_result" 속성에 저장하였습니다.

5. View 작업

insertProduct.jsp

취소 버튼과 등록 버튼이 동작하도록 JS코드를 추가하였습니다.

/* 취소 버튼 */
$("#cancelBtn").click(function() {
	location.href = "/admin/admin"
});

/* 상품 등록 버튼 */
$("#enrollBtn").on("click", function(e) {
	e.preventDefault();
	enrollForm.submit();

});

admin.jsp

'상품 관리 페이지(admin.jsp)'에 상품 등록 결과를 피드백하기 위한 경고창을 띄우기 위해 서버로부터 전달받은 "enroll_result"속성을 활용한 아래의 JS코드를 작성했습니다.(아래의 코드에 <c:out> 태그를 사용했기 때문에 이를 사용하기 위해서 admin.jsp 파일 상단에 JSTL라이브러리 태그 코드를 추가시켜 주어야 합니다.)

<script>
		$(document).ready(function() {
			/* 등록 성공 이벤트 */
			let eResult = '<c:out value="${enroll_result}"/>';
				
			checkResult(eResult);

			function checkResult(result) {

				if (result === '') {
					return;
				}
				alert("상품'" + eResult + "'을 등록하였습니다.");
			}
		});
</script>

6. 테스트

상품 등록 기능이 정상적으로 동작하는지 테스트합니다.

추가로 '상품 관리 페이지(admin.jsp)'에서 경고창이 동작하는지도 확인합니다.

반응형