일단 인강 다 보고 전체적으로 다시 정리해보기
spring 5강 Oracle과 mybatis 연동 실습(회원 목록,등록,수정,삭제)
회원관리의 전체적인 구조
Controller
MemberController.java
Service // 컨트롤러와 모델을 사이에 위치,
//써도 안써도 무방. 서비스는 하나인데 모델 메서드가 여러개인 경우 필요(???) ex) 트랜잭션 처리
MemberService.java 인터페이스
MemberServiceImpl.java 구현 클래스
Model
MemberDAO.java 인터페이스 //DAO를 인터페이스와 구현클래스로 나눠서 진행
MemberDAOImpl.java 구현클래스
MemberDTO.java (자바빈즈와 같이 정보를 저장하는 클래스)
memberMapper.xml sql 매퍼 //mybatis의 sql 명령어가 저장되는 파일
View
member_lsit.jsp
write.jsp //회원 신규 등록 페이지
view.jsp //회원 상세 정보 페이지
+
memberMapper.xml : sql 쿼리 모여있다. ( src/main/resources > mappers )
DAO는 sqlSession 주입받고 ServiceImpl은 DAO 객체 주입받는다.
Controller > Service > DAO 순으로 일을 떠넘기고 처리된 데이터 객체를 주입받는식
mybatis-config.xml : mybatis 설정 파일???, 근데 왜 MemberDTO에 대한 코드 한줄만 있지?
=> MyBatis에 대한 (DB연동같은)다른 설정들은 root-context가 맡고있으므로 그 외 자잘한 설정을 이 파일에 위치
MemberDTO 타입을 리턴(resultType)해야하는 쿼리가 있는데, MemberDTO의 경로가 너무 기니까
typeAliases로 클래스명을 줄여부를수 있게끔 설정한 것 // 이 방법 굳이 쓸 필요 x...
root-context :
Mapper.xml로 끝나는 파일 모두 매핑
sql이 모여있는 파일(도 파일명 Mapper로 끝남 )을 읽어들이고 ( jsp에선 sqlMapConfig.xml // DB연결 정보, 등 )
sqlSession 객체 주입할 수 있게 bean으로 설정
//매퍼파일은 자동업데이트가 제대로 안되는 경우가 잦아서 서버나 툴을 재시작 해야할때도 많다.
회원 등록 프로세스
memberList.jsp [회원 등록] → ( 컨트롤러 경유 ) MemberController의 member/write.do로 매핑된 메서드 실행
( MemberController ←@inject- MemberService ←@inject- MemberDAO ←@inject- SqlSession )
→ (WEB-INF) write.jsp 회원 등록 폼 [완료] → member/insert.do ( 위 과정 )
*JSP mybatis Oracle 연동과 비교
JSP
sqlmap.MybatisManager.java : sqlMapConfig(쿼리파일, DB정보)를 읽어들여 sqlSession 객체 생성
sqlMapConfig : sql 쿼리 담긴 파일 매핑, MyBatis에 DB정보 설정
( sql객체 생성 파일 (db등 mybatis 정보담은 파일 ( sql 파일 ) ) )
Spring
root-context :
sqlSesssionFactory를 bean으로 설정할때 DB정보와 sql 파일 정보를 주고,
sqlSession도 bean으로 설정한다.
위 ( sql객체 생성 파일 (db등 mybatis 정보담은 파일 ( sql 파일 ) ) ) 과정을 root-context가 다 한다.
@RequestMapping된 메서드에 데이터가 넘어올 때
GET방식으로 넘어올땐 매개변수 위치에 @RequestParam ( 생략가능 ) 폼에서 넘어온 데이터를 저장해주는 변수에 붙인다
POST 방식으로 넘어올땐 매개변수 위치에 @ModelAttribute ( 생략가능 ) 폼에서 넘어온 데이터를 저장해주는 변수에 붙인다
스프링이 이 변수에 알아서 폼데이터를 저장해준다.
(get은 파라미터로 받았으니 requestparam, post는 form에서 쓴 각각의 name들 전체를 받았으니 modelattribute로 기억)
정확히는 @RequestParam은 폼의 개별값, @ModelAtrribute는 폼의 전체 데이터(dto) 받아올 때 사용
1 2 3 4 5 | @RequestMapping("member/insert.do") public String insert(@ModelAttribute MemberDTO dto) { memberService.insertMember(dto); return "redirect:/member/list.do"; //목록 갱신 } | cs |
컨트롤러에서 다른 페이지로 데이터를 넘기고자할 때
1. 데이터만 넘길 경우 : @Controller + 메서드에 @RespenseBody OR @RestController
( 다음페이지가 아니라 원래 페이지로 넘어옴 )
1 2 3 4 5 6 7 8 9 10 | @RestController // 스프링 4.0부터 사용 가능 public class SampleRestController { @ResponseBody //데이터 리턴 // json 형식으로 리턴 @RequestMapping("test/doF") // url mapping public ProductDTO doF() { //호출한 곳으로 데이터가 넘어감(json 형식) return new ProductDTO("냉장고",500000); } } | cs |
2. 뷰 정보와 데이터를 함께 넘길 경우 : 리턴타입을 ModelAndView로 하고 넘길 데이터를 (key지정) value 값으로 넣어준다.
(Model에 데이터를 붙이고 리턴으로 포워딩하는거랑 기능상 별 차이는 없는 것같음.
ModelAndView는 Model이랑 리턴 따로따로 할 필요없이 ModelAndview에 둘 다 매개값으로 줘버림)
1 2 3 4 5 6 | @RequestMapping("test/doC") public ModelAndView doC() { Map<String,Object> map=new HashMap<>(); map.put("product", new ProductDTO("샤프",1000)); return new ModelAndView("test/doC","map",map); } | cs |
1. sql developer에서 member 테이블 생성
2. MemberDTO
3. memberDAO
1. sql developer에서 member 테이블 생성
spring 계정 member 테이블 생성
sql
1 2 3 4 5 6 7 8 9 10 11 12 13 | create table member( userid varchar2(50) not null primary key, passwd varchar2(50) not null, name varchar2(50) not null, email varchar2(50), join_date date default sysdate //회원가입 날짜 ); insert into member(userid,passwd,name,email) values('kim','1234','김철수','kim@gmail.com'); select * from member; commit; | cs |
2. MemberDTO
src/main/java -com.example.spring01.model.dto 패키지에 memberDTO 생성
getter / setter와 toString 생성
toString은 객체를 문자열로 변환하여 리턴해주는 java.lang 패키지 Object클래스에서 지원하는 메서드
memberDTO.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | package com.example.spring01.model.dto; import java.util.Date; public class MemberDTO { private String userid; private String passwd; private String name; private String email; private Date join_date; public String getUserid() { return userid; } public void setUserid(String userid) { this.userid = userid; } public String getPasswd() { return passwd; } public void setPasswd(String passwd) { this.passwd = passwd; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Date getJoin_date() { return join_date; } public void setJoin_date(Date join_date) { this.join_date = join_date; } public MemberDTO() { } @Override public String toString() { return "MemberDTO [userid=" + userid + ", passwd=" + passwd + ", name=" + name + ", email=" + email + ", join_date=" + join_date + "]"; } } | cs |
3. memberDAO
src/main/java - com.example.spring01.model.dao 패키지에 memberDAO 인터페이스 생성
memberDAO.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | package com.example.spring01.model.dao; import java.util.List; import com.example.spring01.model.dto.MemberDTO; public interface MemberDAO { public List<MemberDTO> memberList(); public void insertMember(MemberDTO vo); public MemberDTO viewMember(String userid); public void deleteMember(String userid); public void updateMember(MemberDTO vo); public boolean checkPw(String userid, String passwd); } | cs |
같은 dao패키지에 memberDAOImpl 클래스 생성
자동 구현
생성할 때 Interface 부분에서 구현할 인터페이스를 Add하거나
생성하고 implements memberDAO 명시한 후에 Alt + Shift + S > V (자동 오버라이딩, 임플러먼트)
memberDAOImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | package com.example.spring01.model.dao; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import org.apache.ibatis.session.SqlSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Repository; import com.example.spring01.model.dto.MemberDTO; @Repository //서버가 startup될 때 이 클래스가 메모리에 자동으로 등록됨 public class MemberDAOImpl implements MemberDAO { //로깅 처리를 위한 객체 선언 private static final Logger logger= LoggerFactory.getLogger(MemberDAOImpl.class); //SqlSession 객체를 개발자가 직접 생성하지 않고 스프링에서 연결시켜 줌 @Inject //의존관계 주입 SqlSession sqlSession; @Override public List<MemberDTO> memberList() { logger.info("memberList called..."); // sql mapper에 작성된 sql 코드가 실행됨(auto commit & close) List<MemberDTO> list=sqlSession.selectList("member.memberList"); return list; } @Override public void insertMember(MemberDTO vo) { //auto commit & close sqlSession.insert("member.insertMember", vo); } @Override public MemberDTO viewMember(String userid) { return sqlSession.selectOne("member.viewMember", userid); } @Override public void deleteMember(String userid) { sqlSession.delete("member.deleteMember", userid); } @Override public void updateMember(MemberDTO vo) { sqlSession.update("member.updateMember", vo); } @Override public boolean checkPw(String userid, String passwd) { boolean result=false; //mapper에 넘길 값이 2개 이상인 경우 map으로 묶어서 전달 Map<String,String> map=new HashMap<>(); map.put("userid", userid); map.put("passwd", passwd); int count=sqlSession.selectOne("member.checkPw", map); //리턴값이 1이면 true, 0이면 false if(count==1) result=true; return result; } } | cs |
sqlSession의 메서드 : select(One / List) / insert / update / delete
select(One / List) - 처리할 레코드가 하나일 경우 selectOne() 둘 이상일 경우 selectLsit() 사용
@Repository // 서버가 starup될 때 이 클래스가 메모리에 자동으로 등록됨
@Repository : 서버가 올라올때 현재 클래스를 자동으로 메모리에 올려줌, 외부에서 호출할때 @inject로 쉽게 객체 호출 가능
1 2 3 4 5 6 7 | @Override public List<MemberDTO> memberList() { logger.info("memberList called..."); // sql mapper에 작성된 sql 코드가 실행됨(auto commit & close) List<MemberDTO> list=sqlSession.selectList("member.memberList"); return list; } | cs |
sqlSession.commit();
sqlSession.close(); 가 root-context.xml에 자동 설정 돼있다.
1 2 3 4 5 | <!-- SqlSession 객체 주입 --> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache"> <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg> </bean> | cs |
?
1 2 3 4 5 6 7 8 | <!-- SqlSessionFactory 객체 주입 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:/mybatis-config.xml"></property> <property name="mapperLocations" value="classpath:mappers/**/*Mapper.xml"></property> </bean> | cs |
src/main/resources > mappers > memberMapper.xml 만들기
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- 다른 mapper와 중복되지 않도록 네임스페이스 기재 --> <mapper namespace="member"> <select id="memberList" resultType="memberDto"> select * from member order by name </select> <insert id="insertMember"> insert into member (userid,passwd,name,email) values ( #{userid},#{passwd},#{name},#{email} ) </insert> <select id="viewMember" resultType="memberDto"> select * from member where userid=#{userid} </select> <select id="checkPw" resultType="int"> select count(*) from member where userid=#{userid} and passwd=#{passwd} </select> <update id="updateMember"> update member set name=#{name}, passwd=#{passwd}, email=#{email} where userid=#{userid} </update> <delete id="deleteMember"> delete from member where userid=#{userid} </delete> </mapper> | cs |
mybatis-config.xml // 안중요한 설정
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <typeAliases> <typeAlias type="com.example.spring01.model.dto.MemberDTO" alias="memberDto" /> </typeAliases> </configuration> | cs |
Controller에는 @Controller
Model(DAO, DTO)에는 @Repository
Service에는 @Service 붙여서 컴포넌트 스캔
MemberController.java : MemberService 객체를 주입받아 사용
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @Controller //현재 클래스를 Controller Bean으로 등록함 public class MemberController { private static final Logger logger= LoggerFactory.getLogger(MemberController.class); @Inject // MemberService 객체가 주입됨 MemberService memberService; @RequestMapping("member/list.do") //사용자가 요청하는 주소 public String memberList(Model model) { List<MemberDTO> list=memberService.memberList(); logger.info("회원 목록:"+list); model.addAttribute("list",list); //모델에 저장 return "member/member_list"; //출력 페이지로 포워딩 } | cs |
서비스에 memberList() 메서드를 호출하여 List에 멤버리스트를 받고
매개변수 자리에서 선언한 내장객체 model에 리스트를 넣어 멤버리스트 jsp페이지로 포워딩시킨다.
요청과 요청한 데이터 처리
요청한 데이터 처리 과정
jsp페이지에서 요청
→ ( MemberController ←@inject- MemberService ←@inject- MemberDAO ←@inject- SqlSession )
요청
1 2 3 | <td> <a href="${path}/member/view.do?userid=${row.userid}">${row.name}</a> </td> | cs |
DAO
1 2 3 | public MemberDTO viewMember(String userid) { return sqlSession.selectOne("member.viewMember", userid); } | cs |
Service
1 2 3 | public MemberDTO viewMember(String userid) { return memberDao.viewMember(userid); } | cs |
Controller
1 2 3 4 5 | @RequestMapping("member/view.do") public String view(@RequestParam String userid, Model model) { model.addAttribute("dto", memberService.viewMember(userid)); return "member/view"; // view.jsp로 포워딩 } | cs |
//요청받은 페이지 폼 데이터 중 레코드 하나만(userid) 받아와서 데이터 처리 (서비스에 떠넘김)하고 model 객체에 담아 포워딩
코드 작성할때 F4로 클래스 계층 구조를 확인하고 메서드를 선택하여 작성하도록 한다.
// F3으로 보면 인터페이스만 보일수 있으므로 F4로 계층구조를 확인한다.
'Spring > study' 카테고리의 다른 글
스프링 한글 처리를 위한 인코딩 필터 (0) | 2019.06.05 |
---|---|
mybatis #{value}와 ${value} 차이 (0) | 2019.06.05 |
Spring Framework (Legacy) spring01 프로젝트 뜯어보기 (0) | 2019.06.03 |
Spring MVC 전체 흐름 파악하기 (0) | 2019.05.31 |
MVC 패턴에서 Service Model의 역할 (0) | 2019.05.31 |