[210603목] 새프로젝트 자바와 오라클을 연결해 게시판 만들기(인터페이스, 게시글 등록, 전체 글 조회, 글 삭제, 글 검색)
자바와 DB(오라클) 흐름 순서 살펴보기!
UI → Service → Dao → (Mybatis + Mapper) → DB
어제에 이어서 오류난 곳부터 시작!
참고 ) UI는 원래 보통 HTML이기 때문에 만약 글 검색을 다 못하는 경우에는 웹에 가서 할 계획이다.
▶글 검색
쿼리를 먼저 살펴보자면
select * from board
where title like '%날씨%';
select * from board
where writer like '%홍길동%';
날씨나 홍길동과 같으면 키워드를 변수 || #{title} || 같이 표현해 하면 전달하기 어렵지 않지만, title과 writer는 컬럼명이기 때문에 변수로 쓰기 어렵다. 이럴 때 HashMap을 이용해 키와 밸류로 할 수 있다.
select * from board
where title like '%|| #{title} ||%';
글 검색 (작성자, 제목, 글 내용)
★public List<Board> searchBoard(Map<String, Object> map);
비슷한 유형의 쿼리를 변수(컬럼)와 데이터를 함께 뽑아야 하기 때문에 이럴 경우, MAP을 사용하는 것이 좋다.!는 점을 확인할 수 있다.
이제 다음 ReplyMapper로 go!
▶ 댓글 전체 목록(특정 게시글의 전체 댓글 목록을 의미)
public List<Reply> listReply(int board_seq);
쿼리 먼저 살펴보자면
select * from reply where board_seq = 3;
3번 게시글에 대한 댓글
특정 게시글에 대한 댓글이기 때문에 int board_seq가 있어야 한다.
→ board_seq로 조회하지만, 전체를 화면에 출력해야 하기 때문에 List<Reply>이 온다.
▶댓글 저장
public int insertReply(Reply reply);
insert into reply (컬럼명1, 컬럼명2, 컬럼명3) values (데이터1, 데이터2, 데이터3);
service는 dao쪽으로 토스하는 역할만 한다. (하는 일이 딱히 없다.)
패키지 board.ui에 클래스 2개 생성해주기.
main에 BoardUI() 객체를 생성해주고,
다시 UI로 가서 작업 시작!
★UI에서 SERVICE로 보내주기 때문에 생성자, 객체 생성
위와 같이 오류가 발생하면 왼쪽 눌러서 create class BoardService를 눌러주면 오류가 사라진다.
ui에는 service에 넘김
일단 오류만 나지 않게 클래스 생성하기
UI 기본생성자를 생성해주고! Ctrl + space
다시 BoardUI로 가서 기본적인 것들 코드 짜기 ↓
package board.ui;
import java.util.Scanner;
import board.service.BoardService;
public class BoardUI {
Scanner keyin = new Scanner(System.in);
BoardService boardService = new BoardService();
//생성자
public BoardUI() {
String choice = null;
while(true) {
menu();
choice = keyin.next();
switch(choice) {
case "1" :
break;
case "2" :
break;
case "3" :
break;
case "4" :
break;
case "5" :
break;
case "0" :
System.out.println("** 프로그램을 종료합니다.");
return;
default :
System.out.println("** 메뉴를 다시 선택해주세요.");
break;
}
}
}
/**
* 메인 메뉴 출력
*/
private void menu() {
System.out.println(" [[ 게시판 연습 ]] ");
System.out.println("==================");
System.out.println(" 1. 글쓰기");
System.out.println(" 2. 글 전체 목록");
System.out.println(" 3. 글 읽기");
System.out.println(" 4. 글 삭제");
System.out.println(" 5. 글 검색");
System.out.println(" 0. 종 료");
System.out.println("==================");
System.out.println(" > 선택 > ");
}
}
[1.글쓰기]
데이터를 넣는 것이기 때문에 메소드 명은 insertBoard(); (글 삽입)로 만들어 주기
작성자의 값은 한 글자도 괜찮지만 나머지는 안되기 때문에 모두 nextLine()으로 통일!
★next()와 nextLine()의 차이:
next()는 엔터를 데이터로 인식하지 않지만 nextLine()은 데이터로 인식한다.
UI에서 생성한 Board 객체는 service로 보낸다.
Board board = new Board(0, writer, title, textcontent, 0, null);
int result = boardService.insertBoard(board);
UI에서 생성해 service로 보낸 Board 객체는 0 or 1의 값인 정수가 올 것이기 때문에 int result로!
UI에서 생성해 service로 보낸 Board 객체가 DB에 가서 잘 삽입이 되었으면 "1행 삽입하였습니다"라는 값이 돌아온다. 1이 의미하는 것은 삽입, 저장 성공이다.
UI에서 SERVICE로, SERVICE에서 DAO로 보내준다. 그 과정임.
DAO에서는 전혀 다른 프로그램과 연결해야 하기 때문에 할 일이 많다.
★SERVICE에서 DAO로 보내주기 때문에 생성자, 객체 생성
return result; 라는 점! 주의!
dao에 아직 insertBoard()라는 메소드가 없기 때문에 오류가 난다.
오류가 발생한 곳에 올려놓고 왼쪽 클릭해 메소드를 생성한다.
dao 창으로 자동으로 넘어감.
9. DAO 클래스의 내용을 작성한다.
1) MybatisConfig.java 파일에서 생성한 SqlSessionFactory 객체를 가져온다. ( DB접속정보, SQL정보, 별칭정보 등을 가지고 있는 객체 )
2) Mapper 인터페이스에서 작성한 추상메소드를 복사하여 DAO클래스에 붙여넣는다.
3) 해당 메소드에서 DB접속을 하는 코드를 작성한다. SqlSession 객체를 통해서 openSession을 하게 된다.
4) Mapper 인터페이스를 사용할 수 있도록 SqlSession 객체에서 getMapper 메소드를 활용하여 객체로 생성한다.
5) 생성된 객체를 통해서 추상메소드를 실행한다.
6) 실행한 SQL구문이 DML (insert, update , delete) 일 경우에는 반드시 commit을 한다.
7) DB접속 동작은 언제든지 예외가 발생할 수 있는 동작이므로 예외처리를 반드시 해야한다.
8) SQL동작을 다 실행 했다면, DB접속을 종료시켜준다.
★BoardDao라는 클래스에 아래의 코드 삽입!
SqlSessionFactory factory = MybatisConfig.getSqlSessionFactory();
[dao에서 정말 중요한 코드]
dao클래스의 흐름
1) MybatisConfig.java 파일에서 생성한 SqlSessionFactory 객체를 가져온다. ( DB접속정보, SQL정보, 별칭정보 등을 가지고 있는 객체 )
▷ SqlSessionFactory factory = MybatisConfig.getSqlSessionFactory();
2) Mapper 인터페이스에서 작성한 추상메소드를 복사하여 DAO클래스에 붙여넣는다.
▷ insertBoard(board);
3) 해당 메소드에서 DB접속을 하는 코드를 작성한다. SqlSession 객체를 통해서 openSession을 하게 된다.
▷ SqlSession session = factory.openSession();
4) Mapper 인터페이스를 사용할 수 있도록 SqlSession 객체에서 getMapper 메소드를 활용하여 객체로 생성한다.
▷ BoardMapper mapper = session.getMapper(BoardMapper.class);
5) 생성된 객체를 통해서 추상메소드를 실행한다.
▷ int result = mapper.insertBoard(board);
6) 실행한 SQL구문이 DML (insert, update , delete) 일 경우에는 반드시 commit을 한다.
▷ session.commit();
★select을 제외한 insert/delete/update는 꼭 commit을 해줘야 해요!
boardMapper.xml로 gogo! (8, 9번의 순서가 바뀌었지만 문제없음!)
8. Mapper 인터페이스의 추상메소드를 생성한다.
1) 추상메소드의 메소드명칭은 mapper.xml의 SQL을 포함하고있는 태그의 id값과 일치해야한다.
2) 추상메소드의 return type은 SQL을 포함하고 있는 태그의 result type과 일치해야 한다. 단, 없을 경우는 void로 한다. 이때 ( insert , delete , update 태그의 경우에는 int를 활용할 수 도 있다. )
3) 추상메소드의 parameter type은 SQL을 포함하고 있는 태그의 parameter type과 일치해야 한다. 단, 없을 경우는 작성하지 않는다.
<mapper namespace =" " > 안에 해당 인터페이스의 풀네임을 적어줘야 함.
id는 메소드명을 의미하고 parameterType과 resultType을 적어주면 된다.
board.sql에서 그대로 가져와 수정
아래와 같이 #{컬럼명}으로 수정해준다. 절대 세미콜론;도 뒤에 달지 않는다. #{컬럼명}이 getter라고 생각하면 된다.
이렇게 하면 insert 완료!
실행해보기!
작성자는 1글자도 괜찮지만 나머지는 안돼기 때문에 모두 nextLine()으로 통일!
next()와 nextLine()의 차이:
next()는 엔터를 데이터로 인식하지 않지만 nextLine()은 데이터로 인식한다.
System.out.println("> 작성자");
writer = keyin.next();
keyin.nextLine(); // 입력버퍼에 남아있던 엔터를 지우는 역할을 한다.
keyin.nextLine();를 통해 메모리는 가져오지만 변수에 넣는 작업을 하지 않았기 때문에 데이터가 날아간다.
[2. 전체 글 조회 selectAll]
여기에 오타가 있었음
이 과정은 코드도 길고, 스펠링이 틀리는 경우가 많기 때문에 주의해야한다.
10시 30-40분 부터 오류
서비스에서 생성
최근 글이 먼저 올라오도록 DESC 내림차순으로 정렬해준다.
ORDER BY board_seq DESC
출력해보기
web에서는 제목만 보여줌
그래도 오류가 난다.. 속상해..
일단 go...
[3. selectOne 글 읽기]
글 한 개를 조회
쿼리 생각해보기 select * from board where board_seq = ?
글을 조회하기 위해 글 번호를 알아야 한다.
board_seq = keyin.nextInt();
글번호를 입력하는 곳에서 예외가 터질 가능성이 높기 때문에 try~catch문으로 잡아준다.
글 번호라고 생각해서 입력한 문자가 입력버퍼에서 남아 있을 것이기 때문에 입력버퍼를 업애주는 코드 keyin.nextLine(); 해주고 return;으로 되돌아 가야 한다.
boardService.selectOne(board_seq);
→ boardService에게 selectOne(board_seq);를 넘겨주겠다 라는 의미
다시 dao에게 토스!
Mapper.xml로 gogo!
쿼리문 작성!
출력해보기
[4. delete 글 삭제]
delete부터 그냥 내 맘대로 해보기 ...
어치피 수업 다시 듣고 정리해야 할 듯!
하고 넣어 주세요.. 허허
UI → Service
Service → Dao
Dao → Mapper.xml
★[글 검색]
그동안 배우지 않았던 동적 쿼리에 대해!
글 제목으로 검색할 것인지, 작성자로 검색할 것인지에 대한 아이템이 하나 필요하다.