수업/정리

220420 mybatis-2

jumphare 2022. 4. 20. 21:57

* 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 파일에 부등호를 사용해야 할 땐, 특수코드로 바꿔 써야 함! (인식을 제대로 못 하는듯)
다른것도 혹시 모르니 적어놓겠음 써야할 때가 올지도 몰라...


특수코드 몇 개~
&nbsp;
” ” : 공백(스페이스 한 칸)을 의미

&lt;
부등호(<)
 
&gt;
부등호(>)
 
&amp;
앰퍼샌드(&) 기호
 
&quot;
쌍따옴표(“)
 
&#035;
sharp(#)
 
&#039;
따옴표(‘)