목차
- MVC 패턴
- DAO
1. MVC 패턴
MVC 패턴은 Model, View, Controller를 일컫는다.
View ↔ Controller ↔ Service ↔ DAO ↔ DB로 흐름이 이어진다.
- 이때 Service 클래스에서 DML의 트랜잭션(transaction) 관리가 치러져야 한다.
- 예를 들어 DAO에서 insertCategory, insertMenu와 같은 작업이 수행되면 int result = 1;이라는 결과값이 반환된다. 이 결과가 역으로 View까지 도달될 것이다.
❗ 트랜잭션(transaction)
한꺼번에 수행되어야 할 최소 작업 단위를 말한다. 논리적 작업 단위(Logical Unit of Work, LUW)로 불리기도 한다. 즉 논리적으로 한 번에 수행되어야 할 작업 단위인 것이다.
2. DAO
- DAO(Database Access Object)는 데이터베이스 접근용 객체이다. 즉 데이터베이스에 직접 접근하는 객체를 말한다.
- CRUD 연산을 담당하는 기능 단위 메소드들의 집합으로 이루어진 클래스이다.
-- MenuDAO.class
private Properties prop = new Propeties();
- 매 메소드마다 Properties 객체를 작성해 읽어오는 것은 비효율적이므로 필드로 선언한다.
public MenuDAO() {
try {
prop.loadFromXML(new FileInputStream("mapper/menu-query.xml"));
} catch (IOException e) {
e.printStackTrace();
}
}
- 생성자 활용해 XML 파일을 읽어온다.
-- Application.class
MenuDAO menuDAO = new MenoDAO();
Connection con = getConnection();
- MenuDAO 및 Connection 객체를 상단에 선언한다.
-- 1. 메뉴의 마지막 번호 조회
-- menu-query.xml
<entry key="selectLastMenuCode">
SELECT
MAX(A.MENU_CODE)
FROM TBL_MENU A
</entry>
-- MenuDAO.class
public int selectLastMenuCode(Connection con) { //반환형은 int, 전달인자는 Connection으로 설정
PreparedStatement pstmt = null;
ResultSet rset = null;
int maxMenuCode = 0;
String query = prop.getProperty("selectLastMenuCode");
try {
pstmt = con.prepareStatement(query);
rset = pstmt.executeQuery();
if(rset.next()) {
maxMenuCode = rset.getInt("MAX(A.MENU_CODE)");
}
} catch (SQLException e) {
e.printStackTrace();
} finally { //DB와의 연결을 계속 유지하고자 하므로 close(con) 제외
close(rset);
close(pstmt);
}
return maxMenuCode;
}
-- Application.class
int maxMenuCode = menuDAO.selectLastMenuCode(con);
System.out.println("maxMenuCode : " + maxMenuCode);
- 메소드 반환형은 int가 되고, 매개변수 인자로는 Connection이 전달된다.
- DB와의 연결을 계속 유지하기 위해 close(con)은 finally 블럭에서 제외된다.
-- 2. 카테고리 조회
-- menu-query.xml
<entry key="selectAllCategoryList">
SELECT
A.CATEGORY_CODE
, A.CATEOGRY_NAME
FROM TBL_CATEGORY A
</entry>
-- MenuDAO.class
public List<Map<Integer, String>> selectAllCategory(Connection con) {
PreparedStatement pstmt = null;
ResultSet rset = null;
List<Map<Integer, String>> categoryList = null;
String query = prop.getProperty("selectAllCategoryList");
try {
pstmt = con.prepareStatement(query);
rset = pstmt.executeQuery();
categoryList = new ArrayList<>();
while(rset.next()) {
Map<Integer, String> category = new HashMap<>();
category.put(rset.getInt("CATEGORY_CODE"), rset.getString("CATEGORY_NAME"));
categoryList.add(category);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(rset);
close(pstmt);
}
return categoryList;
}
-- Application.class
List<Map<Integer, String>> categoryList = menuDAO.selectAllCategory(con);
for(Map<Integer, String> category : categoryList) {
System.out.println(category);
}
- 메소드 반환형을 지정할 수 있다: List<Map<Integer, String>>
- 메소드 인자로 Connection 타입이 들어온다.
-- 3. 신규 메뉴 등록
-- menu-query.xml
<entry key="insertMenu">
INSERT
INTO TBL_MENU A
(
A.MENU_CODE
, A.MENU_NAME
, A.MENU_PRICE
, A.CATEGORY_CODE
, A.ORDERABLE_STATUS
)
VALUES
(
?
, ?
, ?
, ?
, ?
)
</entry>
-- MenuDAO.class
public int insertNewMenu(Connection con, MenuDTO newMenu) {
PreparedStatement pstmt = null;
int result = 0;
String query = prop.getProperty("insertMenu");
try {
pstmt = con.prepareStatement(query);
pstmt.setInt(1, newMenu.getCode());
pstmt.setString(2, newMenu.getName());
pstmt.setInt(3, newMenu.getPrice());
pstmt.setInt(4, newMenu.getCategoryCode());
pstmt.setString(5, newMenu.getOrderableStatus());
result = pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(pstmt);
}
return result;
}
- 매개변수 인자로 Connection을 쓰고, 추가적으로 전달할 값이 있다면 MenuDTO로 묶어서 보낼 수 있다.
- DTO(Data Transfer Object) 파일은 private 필드, 기본 생성자 및 매개변수 있는 생성자, 설정자(setter)와 접근자(getter), 오버라이딩 된 toString() 메소드로 구성한다.
-- Application.class
-- 3-1. 신규 메뉴 등록을 위한 정보 입력
Scanner sc = new Scanner(System.in);
System.out.print("등록할 메뉴의 이름을 입력하세요 : ");
String menuName = sc.nextLine();
System.out.print("신규 메뉴의 가격을 입력하세요 : ");
int menuPrice = sc.nextInt();
System.out.print("카테고리를 선택해 주세요(식사, 음료, 디저트, 한식, 퓨전) : ");
sc.nextLine();
String categoryName = sc.nextLine();
System.out.print("판매 메뉴에 적용하시겠습니까? (예/아니오) : ");
String answer = sc.nextLine();
-- 3-2. 신규 메뉴 등록을 위한 값 가공
int menuCode = maxMenuCode + 1; //1번에서 조회한 값
int categoryCode = 0;
switch(categoryName) {
case "식사" : categoryCode = 1; break;
case "음료" : categoryCode = 2; break;
case "디저트" : categoryCode = 3; break;
case "한식" : categoryCode = 4; break;
case "퓨전" : categoryCode = 5; break;
}
String orderableStatus = "";
switch(answer) {
case "예" : orderableStatus = "Y"; break;
case "아니오" : orderableStatus = "N"; break;
}
MenuDTO newMenu = new MenuDTO(menuCode, menuName, menuPrice, categoryCode, orderableStatus);
- DTO 파일의 매개변수 있는 생성자에 순서 맞춰 작성한다.
-- 3-3. 신규 메뉴 등록을 위한 메소드 호출하여 등록
int result = menuDAO.insertNewMenu(con, newMenu);
if(result > 0) {
System.out.println("신규 메뉴 등록에 성공하였습니다.");
} else {
System.out.println("신규 메뉴 등록에 실패하였습니다.");
}
✅ dao 계층을 분리할 수 있다.
✅ dao 계층의 의미를 설명할 수 있다.
✅ 실행할 쿼리문을 XML파일(외부 리소스)로부터 불러올 수 있다.
✅ DB와 연동하여 실행할 sql문 별로 메소드를 분리할 수 있다.
✅ sql문을 통해 DB와의 CRUD 결과를 자바의 기본자료형, DTO, collection으로 반환할 수 있다.
'Database' 카테고리의 다른 글
[JDBC] Service | MVC 패턴 | CRUD | Transaction (0) | 2022.02.04 |
---|---|
[Oracle/2nd Review] Part 3. 오라클 객체 및 권한 (0) | 2022.02.04 |
[JDBC] CRUD | INSERT | UPDATE | DELETE (0) | 2022.02.03 |
[JDBC] XML | SQL injection | PreparedStatement (0) | 2022.02.03 |
[Oracle/수업 과제 practice] DML (0) | 2022.01.30 |