Paper.Yellow

Service 실습 본문

데이터베이스/실습

Service 실습

Paper.Y 2022. 8. 19. 16:36

고객, 상품, 주문 세가지 DB를 통해 Service 구현 

 

1.Object 테이블 생성  

고객 - customer

ID USERNAME PASSWORD EMAIL
1 COS 1234 (null)

상품 - product

ID NAME PRICE QTY
1 샴푸 3000 99

두개의 테이블을 생성해서 각각의 임의의 값을 입력

각각의 테이블의 ID는 각자의 Primary_Key로 등록

customer.USERNAME 과 product.NAME은 고유할 수 있게 Unique로 등록

 

CREATE TABLE customer(
    id number(9,0),
    username varchar2(12) not null,
    password varchar2(20) not null,
    email varchar2(50),
    CONSTRAINT customer_pk PRIMARY KEY(id),
    CONSTRAINT customer_username_uk UNIQUE(username) 
);
SELECT * FROM product;

CREATE TABLE product(
    id number(9,0),
    name varchar2(50) not null,
    price number(9,0) not null,
    qty number(9,0) not null,
    CONSTRAINT product_pk PRIMARY KEY(id),
    CONSTRAINT product_name_uk UNIQUE(name) 
);

 

2.관계를 정의할 수 있는 테이블 생성

테이블 사이의 관계를 확인하고 '주문' 테이블을 만든다.

 

주문 - orders 

ID CUSTOMERID PRODUCTID
1 1 1

orders에는 customer.ID / product.ID 를 Foreign_key로 등록

 

CREATE TABLE orders (
    id number(9,0),
    customerId number(9,0),
    productId number(9,0),
    CONSTRAINT orders_pk PRIMARY KEY(id),
    CONSTRAINT orders_customer_fk foreign key(customerId) references customer(id),
    CONSTRAINT orders_product_fk foreign key(productId) references product(id)
);

 

 

3.시퀀스 등록

==========================나중에 시퀀스 포스팅 완료 후 링크 달기

CREATE SEQUENCE CUSTOMER_SEQ
INCREMENT BY 1 
START WITH 1;

CREATE SEQUENCE product_seq
START WITH 1
INCREMENT BY 1;

CREATE SEQUENCE orders_seq
START WITH 1
INCREMENT BY 1;

 

4.DB 연결 

package product.db;

import java.sql.Connection;
import java.sql.DriverManager;

public class DBConnection {

	public static Connection connection() {
		try {
			Class.forName("oracle.jdbc.driver.OracleDriver");
			
			Connection conn = DriverManager.getConnection(
					"jdbc:oracle:thin:@localhost:1521:xe", 
					"SCOTT", 
					"TIGER"
			);
			conn.setAutoCommit(false);
			return conn;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}

5.엔티티(Entity) - ex) Customer

3개 테이블 모두 같은 방식으로 생성되어 예시는 하나만 기록

package product.domain.customer;

public class Customer {
	private int id;
	private String username;
	private String password;
	private String email;
	
	public Customer() {
	
	}
	
	public Customer(int id, String username, String password, String email) {
		this.id = id;
		this.username = username;
		this.password = password;
		this.email = email;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}
	
	
}

 

6.DAO - ex) Customer

package product.domain.customer;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;

public class CustomerDao {
	
	private Connection conn;
	
	public CustomerDao(Connection conn) {
		this.conn = conn;
	}
	
	public int insert(Customer customer) {
		int result = -1;
		try {
			StringBuilder sql = new StringBuilder();
			sql.append("INSERT INTO customer ");
			sql.append("VALUES(customer_seq.nextval, ?, ?, ?)");

			PreparedStatement pstmt = conn.prepareStatement(sql.toString());
			pstmt.setString(1, customer.getUsername());
			pstmt.setString(2, customer.getPassword());
			pstmt.setString(3, customer.getEmail());

			result = pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
	
	public Customer findById(int id) {
		Customer customer = new Customer();
		try {
			PreparedStatement pstmt = 
					conn.prepareStatement("SELECT * FROM customer WHERE id = ?");
			pstmt.setInt(1, id);
			ResultSet rs = pstmt.executeQuery();
			if(rs.next()) {
				customer.setId(rs.getInt("id"));
				customer.setUsername(rs.getString("username"));
				customer.setPassword(rs.getString("password"));
				customer.setEmail(rs.getString("email"));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return customer;
	}
	
	public ArrayList<Customer> findAll() {
		ArrayList<Customer> customerList = new ArrayList<>();
		try {
			PreparedStatement pstmt = 
					conn.prepareStatement("SELECT * FROM customer ORDER BY id DESC");

			ResultSet rs = pstmt.executeQuery();
			while(rs.next()) {
				Customer customer = new Customer();
				customer.setId(rs.getInt("id"));
				customer.setUsername(rs.getString("username"));
				customer.setPassword(rs.getString("password"));
				customer.setEmail(rs.getString("email"));
				customerList.add(customer);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return customerList;
	}
	
	public int updateById(int id, Customer customer) {
		int result = -1;
		try {
			StringBuilder sql = new StringBuilder();
			sql.append("UPDATE customer SET username = ?, password = ?, email = ? ");
			sql.append("WHERE id = ?");
			
			PreparedStatement pstmt = conn.prepareStatement(sql.toString());
			pstmt.setString(1, customer.getUsername());
			pstmt.setString(2, customer.getPassword());
			pstmt.setString(3, customer.getEmail());
			pstmt.setInt(4, id);
			result = pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
	
	public int deleteById(int id) {
		int result = -1;
		try {
			StringBuilder sql = new StringBuilder();
			sql.append("DELETE FROM customer WHERE id = ?");
			PreparedStatement pstmt = conn.prepareStatement(sql.toString());
			pstmt.setInt(1, id);
			result = pstmt.executeUpdate();

		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
}

insert - 추가 
findById - 한건보기
findAll - 목록보기
updateById - 수정
deleteById - 삭제

위 내용으로 3개의 테이블에 대한 DAO를 동일하게 작성

 

7. DTO

 

필요한 서비스 내용 

고객서비스 상품서비스 주문서비스
-고객등록
-고객상세보기
-고객목록보기
-고객수정
-고객삭제
-상품등록
-상품상세보기
-상품목록보기
-상품수정
-상품삭제
-주문하기
-주문취소하기
-고객별주문목록보기 <<==!!

고객별 주문 목록보기는 하나의 테이블 값으로는 구현 불가.

세개의 테이블 값을 INNER JOIN으로 쿼리를 짰다. 

 

DTO 생성

package product.dto;

public class OrderRespDto {
	private int id;
	private String username;
	private String name;
	private int price;
	
	public OrderRespDto() {
	
	}

	public OrderRespDto(int id, String username, String name, int price) {
		this.id = id;
		this.username = username;
		this.name = name;
		this.price = price;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getPrice() {
		return price;
	}

	public void setPrice(int price) {
		this.price = price;
	}
	
	
}

 

 

OrdersDAO에 추가로 구현

public ArrayList<OrderRespDto> findByIdToOrderList(int customerId) {
		ArrayList<OrderRespDto> dtoList = new ArrayList<>();
		try {
			StringBuilder sql = new StringBuilder();
			sql.append("select o.id, c.username, p.name, p.price ");
			sql.append("from orders o ");
			sql.append("INNER JOIN customer c ");
			sql.append("ON o.customerId = c.id ");
			sql.append("INNER JOIN product p ");
			sql.append("ON o.productId = p.id ");
			sql.append("WHERE c.id = ?");
			
			PreparedStatement pstmt = 
					conn.prepareStatement(sql.toString());
			pstmt.setInt(1, customerId);

			ResultSet rs = pstmt.executeQuery();
			while(rs.next()) {
				OrderRespDto dto = new OrderRespDto();
				dto.setId(rs.getInt("id"));
				dto.setUsername(rs.getString("username"));
				dto.setName(rs.getString("name"));
				dto.setPrice(rs.getInt("price"));
				dtoList.add(dto);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return dtoList;
	}

 

8.Service

마음데로 짤 수도 있지만 실수를 할 수 있기에,

실무에서 신입으로 지시를 받을때 상사에게 지시를 받을때 예시처럼 Service 목록을 받았다. 

package product.service;

import java.util.ArrayList;

import product.dto.OrderRespDto;

public interface OrderService {
	public void 주문하기(int customerId, int productId);
	public void 주문취소하기(int id);
	public ArrayList<OrderRespDto> 고객별주문목록보기(int customerId);
}

interface는 하나의 키로 여러개의 메서드를 실행하는 방법도 있지만, 여기서는 메서드에 강제성을 부여하기 위해 사용됐다.

 

9.ServiceImpl

사실 이전까지는 엔티티/DAO 모두 처음 받은 예시를 따라치고 값만 대입해서 바꾸면 되는거라 어떻게든 따라했는데, 

응용된 요구사항을 받으니 어떻게 실행해야하는지 너무 막막했다. 

심지어 제일 첫번째. 재고확인 ( 재고가 0보다 큰가? product findById) 조건마저도 어떻게해야할지 상상이 가지 않았다. 

 

그래서 조건을 쪼개서 보려고 했다. 

주문하기

1) 재고확인 

>재고가 0보다 큰걸 확인하려면 상품을 하나 검색한 후 그 상품에 대한 재고 값을 알아야 한다. 그리고 그 값이 0보다 크다면 재고가 있음

>productDao의 findById로 값을 조회하고, .getQty의 값을 가져와서 if문으로 0보다 크면 실행 0이라면 실행하지 않도록하기

2) 주문하기

조회(read)가 아닌 수정/추가/삭제(write)에서 result = -1; 이 포함되어 있는걸 사실 이해하지 못하고 코드만 따라쳤는데 App 클래스들에서 result의 값이 1인지 검증을 하는 부분이 보였다. 

Dao에 들어가봤다.

 

result의 값이 왜 필요한지 이해가 안 됐다.

이걸 보고 낫보고 기억자도 모른다고 하는걸까. 1이 정상 실행인건 알겠는데 그래서 그게 왜?? 라는 생각 밖에 안 들었다. 

거기다가 코드를 비슷하게 쳤는데 오류가 나는거다. 도대체 뭘 입력해야할지 떠오르지 않았다.

 

포기하고 3. 재고 -1하기를 시도했다.그런데 왜 int로 받아야 하는지 이해가 가지 않았다. 

 

한참 고민하다가 주문취소하기가 더 쉬워보여서 시도했다.

그러다가 문득 쿼리를 작성하고 정상적으로 실행된 것을 확인 한 후에야 최종 실행에서 1(정상실행)의 값을 확인 한 후 commit 한다는걸 깨달은거다.

 

하나라도 실행이 되지 않으면 안되니까 if문 조건에 and를 넣었다.

이걸 깨달으니 주문하기는 쉬운 응용이지.

 

최종코드

package product.service;

import java.sql.Connection;
import java.util.ArrayList;

import product.domain.orders.Orders;
import product.domain.orders.OrdersDao;
import product.domain.product.Product;
import product.domain.product.ProductDao;
import product.dto.OrderRespDto;

public class OrderServiceImpl implements OrderService{

	private Connection connection;
	private ProductDao productDao;
	private OrdersDao orderDao;
	private Orders orders;
	
	public OrderServiceImpl(Connection connection, ProductDao productDao, OrdersDao orderDao) {
		this.connection = connection;
		this.productDao = productDao;
		this.orderDao = orderDao;
	}

	@Override
	public void 주문하기(int customerId, int productId) {
		// 1. 재고확인 ( 재고가 0보다 큰가? product findById)
			Product o =  productDao.findById(productId);
			if(o.getQty() >0) {
				// 2. 주문하기 ( order insert)
				int result1 = orderDao.insert(orders);
			// 3. 재고 -1 하기 ( product updateByIdToQty)
				int result2 = productDao.updateByIdToQty(productId);
				try {
					if(result1==1 && result2 ==1) {
						connection.commit();
					}else {
						connection.rollback();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				
			}else {
				System.out.println("재고없음");
			}
			
	}
	
	@Override
	public void 주문취소하기(int id) {
		// 1. order deleteById
		int result1 = orderDao.deleteById(id);
		// 2. product qty + 1 하기
		int result2 = productDao.updateByIdToQty2(id);
		try {
			if(result1==1 && result2 ==1) {
				connection.commit();
			}else {
				connection.rollback();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public ArrayList<OrderRespDto> 고객별주문목록보기(int customerId) {	
	return orderDao.findByIdToOrderList(customerId);
	}

	
}

 

10.MainApp

package product;

import java.sql.Connection;
import java.util.ArrayList;

import product.db.DBConnection;
import product.domain.customer.CustomerDao;
import product.domain.orders.OrdersDao;
import product.domain.product.ProductDao;
import product.dto.OrderRespDto;
import product.service.OrderService;
import product.service.OrderServiceImpl;

public class MainApp {

	public static void main(String[] args) {
		Connection conn = DBConnection.connection();
		
		CustomerDao customerDao = new CustomerDao(conn);
		ProductDao productDao = new ProductDao(conn);
		OrdersDao orderDao = new OrdersDao(conn);
		
		OrderService orderService = new OrderServiceImpl(conn, productDao, orderDao);
		
		// given
		int customerId = 1;
		
		ArrayList<OrderRespDto> orderRespDtoList = 
				orderService.고객별주문목록보기(customerId);
		
		for (int i = 0; i < orderRespDtoList.size(); i++) {
			System.out.println(orderRespDtoList.get(0).getId());
			System.out.println(orderRespDtoList.get(0).getUsername());
			System.out.println(orderRespDtoList.get(0).getName());
			System.out.println(orderRespDtoList.get(0).getPrice());
		}
		
		orderService.주문하기(customerId, customerId);
		
		orderService.주문취소하기(customerId);
				
	}

}

 

고객별주문목록보기 풀이와 주문하기, 주문취소하기에 대한 주석힌트를 받은 상태로 구현한거라 온전히 내 힘으로 푼건 아니지만 몇시간동안 머리 굴려서 혼자 풀어냈다는게 뿌듯하다. 

 

주말과제

Board [id, title, content + memberId], Member [id, username, password], Comment[id, content, boardId, memberId]

세개의 테이블로 엔티티 / DAO / DTO (Board id, title, username, 댓글수) 구현

힌트 OUTER JOIN 사용.

'데이터베이스 > 실습' 카테고리의 다른 글

주말 과제  (0) 2022.08.22
데이터베이스 CRUD 생성  (0) 2022.08.16