220420 mybatis-2
* maven project 구조
maventest - src - main - java <- Controller, Service, DTO, DAO
★ - resources <-MyBatis 환경설정 파일, SQL문 파일(.xml)
- webapp <- View 페이지
-WEB-INF - web.xml <-project 환경설정 파일
- pom.xml <- Maven 환경설정 파일
mybatis : DAO 객체와 SQL문을 Mapping해주는 Persistence Framework 즉, Data Access Layer에 속하는 프레임워크
---> maven+환경설정파일 2개 더 추가됨
pom.xml : dependency (의존 라이브러리) 추가(설치)하는 곳
mapper.xml : sql문 파일
mybatis-config.xml : 서버 연결 환경설정 파일
db.properties : 서버 연결 정보 (id, pw, url) 담긴 파일
*MyBatis 연동하기
JDBC, DBCP, ORM프레임워크
ORM -> 테이블 컬럼명과 변수명을 동일하게 설정할 경우 자동으로 맵핑이 일어나게 함 -> 소스코드를 줄여준다!
Mybatis는 기존 dao를 처리하던 service class에서 dao부분이 mapper.xml로 분리된 형태!
MemberDAO에서 SqlSession 인터페이스를 이용해 sql문 처리 요청
-> mybatis-config.xml에서 환경설정(서버 연결)
-> member.xml(매퍼)에서 sql문 실행
-> 실행 후 select는 리턴값을 받을것이고 CRUD는 정상 동작 시 1을 리턴하게 될 것. 이걸 DAO가 받아서 넘겨주게 된다!
- SqlSession 메소드
insert -> int insert()
update -> int update()
delete -> int delete()
select -> Object selectOne() : 검색결과가 1개
-> List selectList() : 검색결과가 n개
*Model1 이어서~
4. 회원목록
list.jsp : DAO로 list() 불러옴
---> 전체 목록을 불러오기 때문에 따로 매개변수를 넣지 않아도 됨
---> select 값이 n개이기 때문에 리턴받는 데이터형은 List<dto> 형태여야 함
List<Member> list = md.list();
↓
DAO.java
session = getSession();
list = session.selectList("list");
//selectList ---> 결과가 하나 이상일 경우 사용
↓
member.xml
<select id="list" resultType="member">
select * from member22
</select>
//받은 매개변수가 없으니 parameterType은 생략, 리턴시킬 데이터타입만 정의(resultType)
//전체 목록 불러온 걸 member(dto)형으로 넘김 (다수의 dto가 넘어가게 되겠지)
↓
DAO.java : 리턴받은 member(dto)들이 list에 담김 ---> 기존 rs.next()로 하나씩 불러올 필요 없다는 장점!
list 리턴
↓
list.jsp : for문으로 받아온 list값을 출력!
<tr><td><%=list.get(i).getId() %></td><td><%=list.get(i).getPassword() %></td>
list.get(i).getId() = list의 i번째 dto를 가져올 건데 그 중에 변수명이 id인 값을 빼내겠다는 의미
5. 수정
updateForm.jsp : DAO로 select() 불러옴
---> 수정할 회원의 id를 매개변수로 넘겨 정보를 받아올 것
---> select 값이 1개이기 때문에 리턴받을 데이터형은 member(dto)여야 함
String id = request.getParameter("id");
MemberDao md = new MemberDao();
Member mem = md.select(id);
↓
DAO.java
session = getSession();
mem = (Member) session.selectOne("select", id);
//selectOne ---> 결과가 하나일 경우 사용, 강제형변환은 시켜도 되고 안 시켜도 됨 근데 시키는 버릇을 들이는게 낫지
↓
member.xml
<select id="select" parameterType="String" resultType="member">
select * from member22 where id = #{id}
</select>
//parameterType, resultType 둘 다 정의해야 함 (받는 값 내보내는 값 둘 다 존재하니까)
↓
DAO.java : 리턴받은 member(dto)를 그대로 넘김 -> 얘도 rs.next() 안 써도 돼서 편함
↓
updateForm.jsp : 받아온 dto를 이용해 정보 출력
<input type="hidden" name="id" value="<%=mem.getId() %>">
<input type="text" name="id" value="<%=mem.getId() %>" disabled="disabled"></td></tr>
// disabled="disabled" -> 얘는 수정도 안 되고 값도 넘어가지 않기 때문에 위에 hidden으로 따로 id를 넘겨줘야 함
// 만약 수정 안 되면서+값도 전달하고 싶다면 readonly를 사용할 것!
↓
updatePro.jsp : updateForm에서 입력된 값을 useBean으로 member(dto)에 셋팅
+ DAO 객체 생성해 update() 호출
int result = md.update(mem);
↓
DAO.java
session = getSession();
result = session.update("update", mem);
//update는 리턴값이 결과 여부를 판별하는 int형임 헷갈리지 말 것.
↓
member.xml
<update id="update" parameterType="member">
update member22 set password = #{password} where id = #{id}
</update>
//update는 자동으로 int형으로 리턴되기 때문에 resultType 사용할 필요도 없고 하면 안 됨
#{id}=member.getId() #{password}=member.getPassword()
↓
DAO.java : 리턴
↓
updatePro.jsp : if문으로 리턴받은 값을 판별해 성공 여부 메시지 출력
↓
성공 시 list로 이동, 실패 시 수정폼으로 뒤로가기
6. 삭제
delete.jsp : DAO 객체 생성 후 id를 매개변수로 delete() 불러옴
String id = request.getParameter("id");
MemberDao md = new MemberDao();
int result = md.delete(id);
↓
DAO.java
session = getSession();
result = session.delete("delete", id);
↓
member.xml
<delete id="delete" parameterType="String">
delete from member22 where id = #{id}
</delete>
↓
DAO.java : 리턴
↓
delete.jsp : if문으로 리턴받은 값을 판별해 성공 여부 메시지 출력
↓
성공(또는 실패여도) 시 list로 이동
*Model2 회원관리로 연습
: 근데 이제 사이에 service class만 추가된 거지... jsp -> service -> dao -> mapper.xml -> dao -> service -> jsp 이 순서
차이는 dao->mapper->dao 밖에 없으니까 이부분 중심으로 체크해놓을 것
1. 회원가입
DAO.java
SqlSession session = getSession();
result = session.insert("insert", member);
↓
mapper.xml
<insert id="insert" parameterType="member">
insert into member0609 values(#{id},#{passwd},#{name},#{jumin1},#{jumin2},
#{mailid},#{domain},#{tel1},#{tel2},#{tel3},#{phone1},#{phone2},#{phone3},
#{post},#{address},#{gender},#{hobby},#{intro},sysdate)
</insert> //받은 dto 필드 다 집어넣기
↓
DAO.java : 리턴받은 값을 if문으로 갈라서 성공여부 메시지 출력
+) ID 중복검사
ajax로 idcheck.do -> idcheck.java -> dao 넘어옴
DAO.java
SqlSession session = getSession();
MemberDTO member = session.selectOne("idcheck", id);
↓
mapper.xml
<select id="idcheck" parameterType="String" resultType="member">
select * from member0609 where id = #{id}
</select>
↓
DAO.java : dto값 리턴
↓
idcheck.java : 리턴값을 out객체로 브라우저에 출력! -> 그래야 ajax의 success로 값을 넘길 수 있음
2. 로그인
DAO.java : 입력받은 id, password를 매개변수로 넘김
SqlSession session = getSession();
MemberDTO member = session.selectOne("idcheck", id); //입력받은 id와 일치하는 회원이 있는지 확인 (idcheck 재사용)
↓
mapper.xml
<select id="idcheck" parameterType="String" resultType="member">
select * from member0609 where id = #{id}
</select>
----> member(dto)로 dao에 리턴됨!
↓
DAO.java
//--------------> 만약 id가 존재하지 않는다면 리턴받은 member==null이므로 result=0 (초기값 그대로 리턴)
if(member != null) { // 일치하는 회원이 존재할 때
if(member.getPasswd().equals(passwd)) { //회원 비밀번호와 입력받은 비밀번호를 비교
result = 1; // 맞으면 회원인증 성공
}else {
result = -1; // 회원인증 실패
}
}
+) 여기서 굳이 아이디가 없다/비밀번호가 다르다 나누는건 보안 상 크게 좋지 못하므로 로그인 성공(result=1) 외엔 다 실패로 퉁치게 하는게 좋다고 함
↓
login.java : 리턴받은 result 값을 if문으로 갈라서
로그인 성공 -> id 세션값 공유 -> main.jsp으로 forward
로그인 실패 -> out객체로 로그인 실패 메시지 뿌린 후 뒤로가기-out객체 닫고-return null
out.println("<script>");
out.println("alert('로그인 실패');");
out.println("history.go(-1)");
out.println("</script>");
out.close();
return null;
3. 로그아웃 : db연동할 게 없으므로 service class까지 갈 것 없이 바로 logout.do -> logout.jsp로 넘어감
session.invalidate(); //세션 삭제
공유되는 세션값 전부 삭제 후 로그아웃 메시지 출력 -> main으로 이동하면 됨
4. 정보 수정
updateMember.java : 기존 회원정보 가져와서 폼에 넣어줘야 함
세션영역으로 공유되고 있는 id를 매개변수로 dao.getMember() 호출
HttpSession session = request.getSession();
String id = (String)session.getAttribute("id");
MemberDTO member = dao.getMember(id);
↓
DAO.java : 입력받은 id로
SqlSession session = getSession();
MemberDTO member = session.selectOne("idcheck", id); //입력받은 id와 일치하는 회원이 있는지 확인 (idcheck 재사용)
↓
mapper.xml
<select id="idcheck" parameterType="String" resultType="member">
select * from member0609 where id = #{id}
</select>
----> member(dto)로 dao에 리턴됨!
↓
DAO.java : 그대로 리턴
↓
updateMember.java : dto 통째로 request영역에 공유함
+) 여기서 체크박스값을 하나의 문자열로 합쳐놓은 건 분리 후 공유해야 함 주의!
↓
updateform.jsp : 뿌려진 정보에서 수정할 거 하고 서브밋
↓
update.java
1. 입력받은 비밀번호가 일치하는지 확인하기 위한 dao.getMember(id) 호출하고, 받은 비밀번호와 입력한 비밀번호가 일치하면
2. 입력받은 정보를 dto에 넣고 그 dto를 매개변수로 dao.update(member)에 넘김
↓
DAO.java : dto 매개변수로 넘김
+) 여기서 체크박스값을 하나의 문자열로 합쳐놓고 넘겨야 함 주의!
SqlSession session = getSession();
result = session.update("update", member);
↓
mapper.xml
<update id="update" parameterType="member">
update member0609 set name=#{name}, jumin1=#{jumin1}, jumin2=#{jumin2},
mailid=#{mailid}, domain=#{domain}, tel1=#{tel1}, tel2=#{tel2}, tel3=#{tel3},
phone1=#{phone1}, phone2=#{phone2}, phone3=#{phone3}, post=#{post}, address=#{address},
gender=#{gender}, hobby=#{hobby}, intro=#{intro} where id = #{id}
</update>
↓
DAO.java : 리턴
↓
update.java : 리턴받은 값을 if문으로 갈라서 성공여부 메시지 출력 (이거 Spring에서는 팝업 메시지창 띄우는 방법 배울거래!)
5. 정보 삭제
delete.jsp : hidden으로 넘겨받은 id랑 입력받은 password로
1. dao.getMember(id)로 회원정보 구해서 password 서로 일치하는지 확인하고
(비번 불일치 시 out객체로 메시지 뿌리고 뒤로가기 return null 처리)
2. 비번이 일치하면 id를 dao.delete(id)로 고대로 넘김
DAO.java
SqlSession session = getSession();
result = session.delete("delete", id);
↓
mapper.xml
<delete id="delete" parameterType="String">
delete from member0609 where id = #{id}
</delete>
↓
DAO.java : 그대로 리턴
↓
delete.java : 리턴받은 값을 if문으로 갈라서 성공여부 메시지 출력 + 세션 공유 삭제 -> 로그인폼으로 이동
*Model2 게시판으로 mybatis 연습.. 했다!
특별히 체크해야 하는 부분만 필기
★★
<insert id="board_insert" parameterType="board">
insert into model22 values(model22_seq.nextval,#{board_name},
#{board_pass},#{board_subject},#{board_content},
#{board_file,jdbcType=VARCHAR},model22_seq.nextval,0,0,0,sysdate)
</insert>
#{board_file,jdbcType=VARCHAR}
---> jdbcType=VARCHAR 이 조건이 추가되어 있으면 첨부파일 쪽에 null값을 허용함 (null로 입력될 수 있음)
------> 즉 저게 있으면 첨부파일을 선택하지 않아도(첨부파일 없어도) db에 insert가 될 수 있게 한다는 것.
저게 빠졌을 때 상태 - 오류 작살남
※ parameterType="String"일 경우 #{id}=매개변수명
parameterType="member"일 경우 #{id}=dto 필드명
※ alias로 별칭 만든건 mapper(.xml)파일 내에서만 사용 가능 + dto클래스마다 별칭을 지정해주는 게 좋음
mybatis-config.xml 환경설정파일은 프로젝트 당 1개만 생성
mapper.xml 파일은 테이블마다 1개씩 생성
** DAO에서, SqlSession의 세션을 얻어오는 메소드 getSession()을 생성할 때, 여기서 try catch 구문을 사용했잖아
그럼 이제 getSession 메소드를 가져올 메소드들은, 굳이 사이에 try catch를 넣지 말고
public int idcheck(String id) throws Exception{ ~~~ } 요렇게 예외 발생 시 getSession의 예외구문으로 넘겨도 됨
원래는 예외처리 후에 연결해놓은 커넥션들을 다 닫아주는 과정이 필요했는데 얘는 굳이 필요하지 않음 xml로 넘겨서 거기서 서버와 연결을 하기 때문에...!
** 만약 parameterType을 다양하게, 또는 여러 값을 받고 싶다면?
예를 들면 검색할 때... String으로 sel, find를 받고 int로 startrow, endrow를 받잖아
이런 건
1. dto에 필드를 추가해서 dto 단위로 넘기거나
2. map을 써야 한다고 한다
Map map = new HashMap();
map.put("start", startRow);
map.put("end", endRow);
boardlist = dao.getList(map);
-> 대신 map은 처리 속도가 느리다는 단점이 있어서 일반적으로는 dto에 추가하는 방식을 사용한다고 함
내생각엔, 검색을 여러 게시판에서 사용할 거라면, 검색용 dto를 하나 만드는 게 좋을 것 같음!
** selectList, selectOne의 경우 object형으로 돌려받긴 하는데,
xml파일에서 이미 resultType을 명시해놓았기 때문에 DAO에서 따로 다운캐스팅(강제형변환)시키지 않아도 내부적으로 알아서 변환해 전달할 수 있음!
** xml 파일에 부등호를 사용해야 할 땐, 특수코드로 바꿔 써야 함! (인식을 제대로 못 하는듯)
다른것도 혹시 모르니 적어놓겠음 써야할 때가 올지도 몰라...
특수코드 몇 개~
” ” : 공백(스페이스 한 칸)을 의미
<
부등호(<)
>
부등호(>)
&
앰퍼샌드(&) 기호
"
쌍따옴표(“)
#
sharp(#)
'
따옴표(‘)