(책) 자바 웹을 다루는 기술

Chap 23 마이바티스 프레임워크 사용하기

EunaSon 2023. 9. 19. 16:00

23.1 마이바티스란? 828p                                                 

23.2 마이바티스 설치하기 842p                                       

23.3 마이바티스 이용해 회원 기능 실습하기 845p           

23.4 마이바티스 이용해 회원 정보 CRUD 실습하기 852p

23.5 마이바티스의 동적 SQL문 사용하기 874p                


23.1 마이바티스란?

838p

기존 JDBC

- 반복적으로 구현해야할 SQL 문장이 많고 SQL문이 복잡함

- 연동 과정 : connection -> Statement 객체 생성 -> SQL문 전송 ->결과 반환 -> close

  => SQL문이 소스코드에 섞여 복잡해짐

- 문자열로 SQL문을 만들어 사용하는 방식

 

마이바티스

- 복잡한 SQL문도 SQL Developer에서 사용하듯 표준화된 방법으로 사용 가능(문자열로 안만들어도 됨)

- SQL 실행 결과를 자바 빈즈 또는 Map 객체에 매핑해주는 Persistence 솔루션으로 관리함, 즉 SQL을 소스코드가 아닌 XML로 분리함

- 데이터소스(DataSource) 기능과 트랜잭션 처리 기능을 제공함

 

마이바티스 프레임워크의 구조

DB 연동 시 사용되는 SQL문을 미리 SqlMapConfig.xml에 작성해놓음

> 애플리케이션에서 DB 연동 시 해당 SQL문에서 사용될 데이터를 지원하는 해당 매개 변수에 저장 후 SQL문에 전달함

> 전달된 매개변수와 SQL문을 결합해서 SQL문을 DBMS로 전송, 실행함

> 결과를 애플리케이션에서 제공하는 자료형으로 반환함

 

23.2 마이바티스 설치하기

842p

1. http://www.mybatis.org에 에 접속 > Products 탭을 클릭

2. MyBatis 3 옆에 있는 download 링크를 클릭

3. mybatis-3.4.6.zip 파일을 클릭해 다운로드 함

4. 다운받은 압축 파일의 압축을 해제

5. 압축을 해제한 폴더 안의 mybatis-3.4.6.jar를 복사해서 새로 만든 프로젝트 pro23의 lib 폴더에 붙여넣음, 이 버전에 대응하는 ojdbc6.jar 파일도 복붙함, JSTL 관련 라이브러리도 14장을 참고해서 복붙함

 

23.3 마이바티스 이용해 회원 기능 실습하기

845p

마이바티스를 이용해 회원 테이블과 연동하여 다양한 회원 관련 기능을 수행해보자.

 

1. 마이바티스 설정 파일 작성

- SqlMapConfig.xml : DB 연동 시 반환되는 값을 저장할 빈이나 트랜잭션, 데이터소스 등 마이바티스 관련 정보를 설정함

- member.xml : 회원 정보 관련 SQL문을 설정함

* 설정파일은 src 패키지 아래에 위치해야 함

* SqlMapConfig.xml은 src.mybatis 패키지에서 우클릭 > New > other > XML File 선택하여 생성함

* member.xml은 mybatis 패키지 아래 mybatis.mappers 패키지 생성하여 그 안에 만듦

 

[ SqlMapConfig.xml ]

- <typeAlias> : SQL문으로 값을 전달하거나 SQL문 실행 후 반환되는 레코드를 저장하는 용도로 사용할 빈(memberVO)을 생성함

- <dataSource> : 마이바티스가 연동하는 데이터베이스에 대한 데이터소스를 설정함

- <mappers> : 마이바티스에서 사용할 SQL문이 있는 XML 파일의 위치를 지정함

<!-- pro23/src/mybatis/SqlMapConfig.xml -->
<!-- 앞부분은 책에서 제공하는 파일에서 복붙함.  ?xml ~ !DOCTYPE 부분까지 -->

<configuration>
    <typeAliases>
        <!-- DAO->SQL문으로 값 전달 시 & SQL문 실행 후 DAO로 값 전달 시 사용할 빈을 생성-->
        <typeAlias type="com.spring.ex01.MemberVO" alias="memberVO" />
    </typeAliases>
    
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <!-- 데이터베이스 연결을 설정함-->
            <dataSource type="POOLED">
                <property name="driver" value="oracle.jdbc.driver.OracleDriver" />
                <property name="url" value="JDBC:oracle:this:@localhost:1521:XE" />
                <property name="username" value="scott" />
                <property name="password" value="tiger" />
            </dataSource>
        </environment>
    </environments>
    
    <mappers>
        <!-- 회원기능 관련 SQL문이 있는 member.xml을 읽어들임. 패키지 이름 일치시키지! -->
        <mapper resource="mybatis/mappers/member.xml" />
    </mappers>
</configuration>

 

[ member.xml ]

회원 기능과 관련된 SQL문을 설정함

다른 파일의 SQL문과 구별하기 위해 mapper.member 로 네임스페이스를 지정

반환되는 레코드(회원정보 레코드)를 저장하기 위한 resultMap을 지정함

각 레코드는 하나의 memberVO 객체를 생성 후 레코드의 컬럼값을 지정한 속성(컬럼과 이름이 같은 속성)에 저장함

<select> 태그의 id 속성은 memberDAO에서 SQL문을 구분해서 호출하는 용도로 사용됨, 반환되는 레코드를 id가 memResult (memberVO)인 resultMap에 저장함

<!-- pro23/src/mybatis/mappers/member.xml -->
...
<!-- member.xml 의 네임스페이스를 지정함 -->
<mapper namespace="mapper.member">
    <!-- SQL문 실행 후 반환하는 레코드를 SqlMapConfig.xml의 <typeAlias>에서 지정한 memberVO빈에 저장함-->
    <resultMap id="memResult" type="memberVO">
        <!-- 레코드의 컬럼 이름에 대해 memberVO의 이름이 같은 속성에 값을 저장함-->
        <result property="id" column="id" />
        <result property="pwd" column="pwd" />
        <result property="name" column="name" />
        <result property="email" column="email" />
        <result property="joinDate" column="joinDate" />
    </resultMap>
    
    <!-- DAO에서 <select>의 id 속성을 이용해 해당 SQL문을 호출함, 
    반환되는 레코드는 memResult(memberVO)에 저장-->
    <select id="selectAllMemberList" resultMap="memResult">\
        <![CDATA[
            select * from t_member order by joinDate desc
        ]]>
    </select>
</mapper>

* SQL문의 <, > 같은 연산자들을 XML 파일에서 작성 시 연산자가 아니라 특수문자로 인식하게 됨, 이런 연산자들도 SQL문의 일부임을 알려주기 위해 <![CDATA[ ... ]]> 태그 안에 SQL문을 작성함

 

2. 마이바티스를 이용한 회원 정보 조회 실습

실제 마이바티스와 연동하기 위한 자바 클래스와 JSP를 준비함.

src 패키지 아래 com.spring.ex01 패키지 생성 > MemberDAO, MemberServlet, MemberVO 클래스 생성

WebContent에 test01폴더 생성 후 listMembers.jsp 생성

 

[ MemberServlet 클래스 ]

브라우저에서 요청 시 MemberDAO 객체를 생성한 후 selectAllMemberList() 를 호출하는 서블릿.

MemberDAO.selectAllMemberList() 가 반환한 membersList를 request에 바인딩 후 test01/listMembers.jsp 로 dispatch 포워딩

...

 

@WebServlet("/mem.do")

...

doHandle(...) {

...

MemberDAO dao = new MemberDAO();

List membersList = dao.selectAllMemberList(); // MemberDAO 객체 생성 후 selectAllMemberList()를 호출해서 List 를 반환받음

request.setAttribute("membersList", membersList);

RequestDispatcher dispatch = request.getRequestDispatcher("test01/listMembers.jsp");

dispatch.forward(request, response);

}

 

[ MemberDAO 클래스 ]

SqlMapConfig.xml 파일을 이용해서 마이바티스를 이용해는 sqlMapper 객체를 가져오는 geetInstance() 메서드를 작성,

member.xml의 SQL문을 호출하는데 사용되는 SqlSession 객체를 가져와서(getInstance() 메서드 이용)

여러 개의 레코드를 조회하므로 selectList() 메서드에 실행하고자 하는 SQL문의 id를 인자로 전달함

*** SqlSession 객체 : MyBatis에서 DAO 구현에 필요함(원래 스프링에서는 설정파일 통해 자동주입됨)

...
public class MemberDAO{
    private static SqlSessionFactory sqlMapper = null;
    
    // MemberDAO의 각 메서드 호출 시 SqlMapConfig.xml에서 db 연동 설정 정보 읽어와 sqlMapper 객체 반환
    public static SqlSessionFactory getInstance() {
        if (sqlMapper == null) {
            try {
                String resource = "mybatis/SqlMapConfig.xml";
                Reader reader = Resources.getResourceAsReader(resource);
                sqlMapper = new SqlSessionFactoryBuilder().build(reader); 
                // mybatis를 이용하는 sqlMapper 객체를 가져옴
                reader.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return sqlMapper;
    }
    
    public List<MemberVO> selectAllMemberList() {
        sqlMapper = getInstance();
        sqlSession session = sqlMapper.openSession(); // 실제 member.xml의 SQL문을 호출하는데에 사용됨
        List<MemberVO> memList = null;
        memList = session.selectList("mapper.member.selectAllMemberList"); 
        // 실행하고자 하는 SQL문의 id를 인자로 전달
        return memList;
    }
}

* selectList(query_id) : 852p (23.4 참고), id에 대한 select문을 실행 후 여러 레코드를 List로 반환함

 

[ MemberVO 클래스 ]

SQL문에 전달할 값이나 SQL문을 실행한 후 반환되는 레코드의 값을 속성에 저장함

 

멤버변수 id, pwd, name, email, joinDate 를 선언,

기본 생성자와 인자 4개(joinDate 제외) 갖는 생성자를 선언,

각 속성에 대한 getter와 setter 도 작성함

 

[ listMembers.jsp ]

22장의 listMembers.jsp 복붙.

c:forEach로 ${membersList] 내용 출력함

 

 

23.4 마이바티스 이용해 회원 정보 CRUD 실습하기

852p

마이바티스의 SqlSession 클래스에서 제공하는 CRUD를 실행 시 많이 사용되는 메서드들임.

▼ SqlSession 클래스에서 제공하는 여러 가지 메서드

메서드 기능
List selectList(query_id) id에 대한 select문을 실행한 후 여러 레코드를 List로 반환함
List selectList(query_id, 조건) id에 대한 select문을 실행하면서 사용되는 조건도 전달함
T selectOne(query_id) id에 대한 select문을 실행한 후 지정한 타입으로 한 개의 레코드를 반환함
T selectOne(query_id, 조건) id에 대한 select문을 실행하면서 사용되는 조건도 전달함
Map<K,V> selectMap(query_id, 조건) id에 대한 select문을 실행하면서 사용되는 조건도 전달함.
Map 타입으로 레코드를 반환함.
int insert(query_id, Object obj) id에 대한 insert문을 실행하면서 obj 객체의 값을 테이블에 추가함
int updae(query_id, Object obj) obj 객체의 값을 조건문의 수정 값으로 사용해 id에 대한 update문을 실행함
int delete(query_id, Object obj) obj 객체의 값을 조건문의 조건 값으로 사용해 id에 대한 delete문을 실행함

* insert(), update(), delete() 등 - 업데이트한 행의 개수를 반환(int)함, 쿼리문이 잘 수행되었는지를 확인할 수 있음

 

1. 회원의 ID와 비밀번호 조회 (id 를 통해 이름 또는 비밀번호 조회함)

853p

src 아래 com.spring.ex02 패키지 생성 후 MemberDAO, MemberServlet 클래스를 생성

src 아래 mybatis.mapper 아래 member.xml 생성

 

[ member.xml ]

SQL문에 접근하기 위해 <select> 태그의 id 속성을 설정함

SQL문을 실행했을 때 1개의 데이터를 조회하므로 resultType은 String, int로 지정함 

<!-- pro23/src/mybatis/mappers.member.xml -->
...
<mapper namespace="mapper.member">
...
<!-- DAO에서 이름조회에 사용할 SQL문의 id를 지정함, 반환타입은 String -->
<select id="selectName" resultType="String"> 
    <![CDATA[
        selet name from t_member where id='hong'
    ]]>
</select>

<!-- DAO에서 비번조회에 사용할 SQL문의 id를 지정함, 반환타입은 int -->
<select id="selectPwd" resultType="int"> 
    <![CDATA[
        selet pwd from t_member where id='hong'
    ]]>
</select>
</mapper>

* selectName, selectPwd 모두 id가 'hong' 인 사람의 것을 조회하는 쿼리문임

 

[ MemberServlet 클래스 ]

MemberDAO의 selectName() 또는  selectPwd() 메서드를 호출한 후 각 데이터를 브라우저에 알림창으로 출력함

 

... doHandle(...) {

...

MemberDAO dao = new MemberDAO();

String name = dao.selectName();

// int pwd = dao.selectPwd();

Printwriter pw = response.getWriter();

pw.write("<script>");

pw.write("alert(' 이름 : " + name + " ');" ); // 조회한 이름을 브라우저로 출력함

// pw.write("alert(' 비밀번호 : " + pwd + " ');" );

pw.write("</script>");

}

 

[ MemberDAO 클래스 ]

member.xml의 <select> 태그의 id 속성의 값으로 각 SQL문을 호출 후 <select> 태그의 resultType에 설정한 것과 같은 타임의 변수로 하나의 데이터를 반환함

...

getInstance() {...} // 앞절에서 작성했음, SqlMapConfig.xml 을 참고해 sqlMapper 객체를 반환함

 

public String selectName() {

  sqlMapper = getInstance();

  SqlSession session = sqlMapper.openSession();

  String name = session.selectOne("mapper.member.selectName");

  return name;

}

 

public int selectPwd() {

  sqlMapper = getInstance();

  SqlSession session = sqlMapper.openSession();

  int pwd = session.selectOne("mapper.member.selectPwd");

  return pwd;

}

 

public String selectName() {

  sqlMapper = getInstance();

  SqlSession session = sqlMapper.openSession();

  String name = session.selectOne("mapper.member.selectName");

  return name;

}

 

2. HashMap을 이용한 모든 회원 정보 조회

856p

[ member.xml ]

<resultMap> type 속성에 HashMap이 지정됨 -> SQL 실행 결과, 조회한 레코드의 컬럼명을 key로, 그 값을 value로 해서 차례대로 HashMap에 저장함

selectAllMemberList 쿼리 실행 시 결과 레코드를 HashMap인 memResult에 저장함(resultMap="memResult"), 레코드가 여러개면 List에 여러개의 Map을 담음

 

*** resultType 과 resultMap

resultType 사용 시 클래스를 그대로 사용함(레코드의 컬럼명과 클래스의 속성명이 같아야함), 자동 매핑되어 편리

resultMap 사용 시 원하는 이름으로 사용할 수 있음(레코드의 컬럼명을 내가 지정한 HashMap의 key 이름으로 가져옴)

 단, <resultMap> 태그를 통해 따로 작성해주어야 함, 레코드 컬럼 수가 많다면 번거로워짐

 

<!-- pro23/src/mybatis/mappers/member.xml -->
...
<mapper namespace="mapper.member">
    <!-- 기존의 memberVO type의 resultMap은 주석처리함-->
    <resultMap id="memResult" type="jajva.util.HashMap">
        <result property="id" column="id" />
        ...<!-- id외에도 마찬가지로 pwd, name, email, joinDate 컬럼의 값을 저장하도록 함 -->
    </resultMap>
    
    <select id="selectAllMemberList" resultMap="memResult"> <!-- 조회결과를 HashMap에 담음-->
        <![CDATA[
            select * from t_member order by joinDate desc
        ]]>
    </select>
</mapper>

 

[ MemberServlet.java ]

브라우저에서 서블릿에 요청시("/mem.do") DAO의 selectAllMemberList() 메서드를 호출, 조회한 전체 회원 정보 List를 바인딩 후 listMembers.jsp로 포워딩함

 

...

MemberDAO dao = new MemberDAO();

List membersList = dao.selectAllMemberList(); // 조회한 회원정보를 List에 저장함(List안에는 resultMap으로 지정한 Map이 들어있음)

request.setAttribute("membersList", membersList);

디스패처 통해 "/test01/ListMembers.jsp"로 포워딩

 

[ MemberDAO.java ]

selectAllMemberList() 메서드는 sqlMapper 객체를 가져와서(getInstance() 메서드 호출)

DAO 구현을 위해 openSession()으로 SqlSession 객체 가져옴,

member.xml에 있는 selectAllMemberList ("mapper.member.selectAllMemberList") 를 query_id로 하여 session.selectList의 인자로 넘겨주어 조회된 결과(회원 목록 List)를 memberList에 저장함

 

3. 조건 값으로 회원 정보 조회

858p

검색창(search.jsp) 에서 검색 조건을 입력한 후 member.xml의 SQL문에 전달하여 조건에 대한 회원 정보를 조회하는 예제

 

[ member.xml ]

조건 값으로 조회하는 경우, 브라우저에서 전달되는 값이 있음 -> <select> 태그에 parameterType 속성으로 전달되는 조건값의 데이터 타입 지정함

MemberDAO에서 전달된 조건값을 SQL문의 조건식에 사용 시 #{ 전달된 매개변수이름} 으로 사용함

 

<resultMap> 으로 memberVO 객체의 id를 memResult로 지정, 컬럼명과 memberVO의 속성명을 매칭시킴,

<select id="selectAllMemberList" resultMap="memResult"> - 전체 회원목록 조회 쿼리

<select id="selectMemberById" resultType="memberVO"> - id로 특정 회원 조회, where절의 조건값(id)을 #{id} 로 전달받아 사용함

<select id="selectMemberByPwd" resultMap="memResult"> - pwd로 회원 조회, where절의 조건값(pwd)를 #{pwd} 로 전달받아 사용함

 

[ MemberServlet 클래스 ]

// pro23/src/com/spring/ex03/MemberServlet.java

DAO, VO 객체 생성,

request.getParameter()로 name="action" 으로 넘어온 action값을 가져와 변수에 저장,

조건문을 사용하여 action값에 따라 적합한 dao의 메서드를 호출함

메서드 결과를 바인딩 후 적당한 jsp 페이지로 포워딩하도록 함

 

[ MemberDAO 클래스 ]

- MemberVO selectById(String id) 메서드 : session.selectOne(쿼리id, id(매개변수로 서블릿으로부터 전달받은 값)) 을 사용하여 쿼리문 수행 결과를 MemberVO에 담아 서블릿으로 반환함

- List<MemberVO> selectByPwd(int pwd) 메서드 : session.selectList(쿼리id, pwd(메서드의 매개변수, 서블릿에서 전달받음)) 을 사용해 쿼리문의 수행 결과, MemberVO에 레코드를 저장하여 List에 추가해 서블릿으로 반환함

* pwd는 유일하지 않아도 되므로 pwd로 검색 시 여러 회원이 조회될 수 있음. 따라서 selectOne()이 아닌 selectList()로 조회함

 

[ search.jsp ]

// pro23/WebContent/test02/search.jsp

검색창,

<form> 요소 action 속성으로 ~~~/mem3.do 를 통해 submit 시 MemberServlet으로 요청됨,

  <input> text 박스로 검색 조건을 입력받을 수 있음 (검색할 id 혹은 pwd)

    <select> 태그와 <option> 태그를 이용해 드롭다운 메뉴를 만듦, '전체'(전체회원 조회), '아이디'(id로 검색 조회), '비밀번호'(pwd로 검색 조회) 중 선택할 수 있음, select 태그의 name 속성으로 'action' 을 입력해 <option> value 값을 서블릿에서 사용할 수 있게 함(서블릿에서 request.getParameter("action") -> option의 value값 가져와짐) 

  <input> submit 타입, '검색' 을 클릭 시 해당 폼 태그의 내용이 서블릿으로 넘어감

 

[ memberInfo.jsp ]

조회한 회원 정보를 출력함.

id로 조회시에만 해당 jsp로 포워딩됨(조회 레코드가 1개(서블릿에서 DAO.메서드 호출 결과가 memberVO에 담겨서 반환됨)인 경우)

전체 회원 조회 or pwd로 조회 시 쿼리 수행 결과가 List에 담겨 반환되므로 listMembers.jsp 로 포워딩됨

 

 

4. 회원 정보 추가

864p

com.spring.ex04 패키지 생성, MemberDAO, MemberServlet 복붙

WebContent 폴더에 test03 폴더 생성, listMembers.jsp 복붙, memberForm.jsp 생성

 

[ member.xml ]

insert문을 작성,

parameterType으로 memberVO를 지정(MemberDAO에서 추가할 회원정보를 MemberVO의 속성에 저장해서 넘김)

쿼리문의 values 에는  #{id} 등의 형식을 통해 MemberVO의 속성이름으로 값을 가져와 사용함

 

<insert id="insertMember" parameterType="memberVO">

...

insert into t_member(id, pwd, name, email)

values(#{id}, #{pwd}, #{name}, #{email}) // memberVO의 속성 이름에 저장된 값을 value로 설정함

...

 

[ MemberServlet.java ]

브라우저에서 전송된 action 값이 insetMember면 (memberForm.jsp 에서 form 태그의 action 속성을 통해 전달됨)

request.getParameter("id") 등으로 id, pwd, name, email을 가져와 변수에 저장 후 memberVO 객체에 setter로 속성값 설정 후 dao.insertMember(memberVO) 메서드 호출,

/mem4.do?action=listMembers 로 포워딩함

 

[ MemberDAO.java ]

DAO에서 insert문을 사용하려면 SqlSession 클래스의 insert() 메서드를 사용함,

인자로 쿼리id와 추가할 내용을 담은 객체(memberVO) 를 전달함

* insert() -  추가된 데이터(행)의 개수를 반환하므로 return값이 있음

session.commit() 으로 수동커밋함

 

[ memberForm.jsp ]

회원가입창, form 태그의 action 속성에 ${contextPath}/mem4.do?action=insertMember 으로 작성하여

action값을 서블릿에 전달함

 

 

5. HashMap을 이용한 회원 정보 추가

867p

4에서는 회원정보 추가시 MemberVO에 회원정보 저장 후 쿼리문으로 전달했는데

이번에는 HashMap에 회원정보 저장하여 테이블에 추가해보자

 

[ member.xml ]

<insert> 의 parameterType을 memberVO가 아닌 java.util.HashMap으로 지정함

values에는 마찬가지로 #{ id } 등으로 값을 가져오는데,

이는 매개변수로 넘어온 HashMap의 key 이름을 써주어서 값을 가져오는 방식임

 

[ MemberServlet 클래스 ]

회원가입창에서 회원정보 입력 후 '가입하기' 누르면 서블릿으로 action 값 insertMember2 이 넘어옴,

getParameter()로 입력한 회원정보 가져와 변수에 저장 후,

HashMap인 memberMap을 생성하여 회원정보를 저장함,

dao.insertMember2(memberMap) 호출,

/mem4.do?action=listMembers 를 nextPage로 지정하여 회원 목록창으로 포워딩함

 

[ MemberDAO 클래스 ]

insertMember2(Map<String, String> memberMap) 에서

SqlSession 클래스의 insert() 메서드 호출 시 두번째 인자로 추가할 회원정보를 담고있는 HashMap인 memberMap을 지정함

 

[ memberForm.jsp ]

<form> 태그의 action 속성을 ${ contextPath }/mem4.do?action=insertMember2 로 변경함 (원래는 action=insertMember 였음, 4에서 실습한 예제에서 확인)

 

6. 회원 정보 수정

869p

WebContent/test03 에 modMember.jsp 를 추가함

 

[ member.xml ]

update문은 <update> 태그를 이용해서 작성함, parameterType으로 memberVO를 지정해줌

#{ memberVO의 속성명 } 으로 해당 속성의 값을 가져와 update할 회원정보의 값을 설정함

...
<update id="updateMember" parameterType="memberVO">
    <![CDATA[
        update t_member
        set pwd=#{pwd}, name=#{name}, email=#{email}
        where id=#{id}
    ]]>
</update>
...

 [ MemberServlet ]

회원수정창(modMember.jsp)에서 수정할 정보 입력 후 '수정하기' 누르면 서블릿으로 "action" 이라는 name으로 updateMember 가 전달됨,

request.getParameter()로 id, pwd, name, email을 가져와 변수에 저장 후

memberVO에 setter로 값 설정,

dao.updateMember(memberVO) 호출함,

nextPage로 /mem4.do?action=listMembers 를 지정하여 포워딩함

 

[ MemberDAO ]

SqlSession 클래스의 update() 메서드를 이용함,

첫번째 인자로는 member.xml의 쿼리id를, 두번째 인자로는 서블릿에서 전달받은 memberVO를 지정함,

session.commit() 으로 변경사항 영구저장함

 

[ modMember.jsp ]

회원정보 수정창, form태그의 action 속성값으로 ${contextPath}/mem4.do?action=updateMember 를 지정하여

서블릿에 action명 updateMember를 전달함

 

7. 회원 정보 삭제

872p

회원목록창(listMembers.jsp) 에서 삭제할 회원 id를 전달받아 회원정보를 삭제해보자.

 

[ member.xml ]

delete문은 <delete> 태그를 이용해 작성함,

parameterType으로는 String을 지정함(전달받는 것= 삭제할 회원id = String타입)

전달된 id를 조건값(where절에서 사용)으로 함

...
<delete id="deleteMember" parameterType="String">
    <![CDATA[
        delete from t_member
        where id=#{id}
    ]]>
</delete>
...

[ MemberServlet ]

회원목록창(listMembers.jsp)에서 서블릿으로 전달된 action값이 deleteMember 면

getParameter("id")로 전달된 삭제할 id를 가져와 변수에 저장 후

dao.deleteMember() 메서드의 인자로 전달함,

nextPage="/mem4.do?action=listMembers" 로 포워딩

 

[ MemberDAO ]

SqlSession 클래스의 delete() 메서드를 이용해 delete문을 실행함,

메서드의 두번째 인자값으로 전달된 id를 설정함,

session.commit() 으로 커밋까지 완료하기

 

[ listMembers.jsp ]

회원목록창, 삭제하기 링크를 추가함

=>

<c:forEach>로 ${ membersList } 출력할 때,

<td>에 <a href="${contextPath}/mem4.do?action=deleteMember&id=${member.id}" 를 추가함  

서블릿으로 action 과 id 가 전달되도록 함

 

 

23.5 마이바티스의 동적 SQL문 사용하기

874p

공통 SQL문에 대해 where절의 조건값 유무에 따라 동적으로 공통SQL문에 조건절을 추가하는 데에 사용됨

예를 들어, 같은 테이블에서 전체회원 조회/id조건으로 조회/id,pwd 조건으로 조회 모두 select문은 동일함 -> 공통SQL문에 조건절만 추가하면 더욱 편리하게 사용 가능

 

동적SQL문은 주로 where절을 동적으로 추가함,

JSP의 JSTL에서 사용되는 코어 태그들과 유사함

 

동적 SQL문의 특징

- SQL문의 조건절에서 사용함

- 조건절(where)에 조건을 동적으로 추가함

- JSTL과 XML 기반으로 동적 SQL문을 작성함

 

동적 SQL문 구성 요소

- if

- choose(when, otherwise)

- trim(where, set)

- foreach

 

1. <if> 태그로 동적 SQL문 만들기

875p

<where> 태그 안에 <if> 태그 사용, if 태그의 조건식이 존재(true)하면 <if> 태그 안의 내용을 where절로 추가함

<where>
    <if test='조건식'>
        추가할 구문, 조건식이 존재할 경우 where절이 SQL문에 추가된
    </if>
</where>

실습파일 위치

src/com/sprint/ex04 - MemberDAO, MemberServlet

src/mybatis - SqlMapConfig.xml

src/mybatis/mappers - member.xml

WebContent/test03 - listMembers.jsp, memberForm.jsp, modMember.jsp, searchMember.jsp

 

[ member.xml ]

<where> 태그를 이용해 SQL문의 where절을 구성함

첫번째 <if> 태그 - name속성 값을 체크해 공백 이나 null 이 아니면 name='name속성값'을 공통 SQL문 뒤에 추가함

두번째 <if> 태그 - email속성 값을 체크해 공백이나 null이 아니면 email='email속성값' 을 공통 SQL문 뒤에 추가함

<select id="searchMember" parameterType="memberVO" resultMap="memResult">
    <![CDATA[
        select * from t_member <!-- 공통 SQL문 -->
    ]]>
    <where>
        <if test="name != '' and name != null">
            name=#{name}
        </if>
        <if test="email != '' and email != null">
            email=#{email}
        </if>
    </where>
    order by joinDate desc
</select>

[ MemberServlet ]

action값이 searchMember 이면 검색창에 입력한 name 과 email 을 getParameter()로 가져와 변수에 저장,

memberVO에 setter로 값 저장 후 dao.searchMember()에 인자로 전달함,

메서드로 반환받은 List를 request에 바인딩, test03/listMembers.jsp로 포워딩

 

[ MemberDAO ]

SqlSession 클래스의 selectList() 메서드를 호출함, 두번째 인자로 memberVO 설정

 

[ searchMember.jsp ]

form 태그 안에 검색조건을 입력할 수 있도록 이름을 입력할 input태그와 이메일을 입력할 input 태그를 작성,

hidden input 태그로 name=action으로 value=searchMember 를 서블릿으로 전달함

 

 

2. <choose> 태그로 동적 SQL문 만들기

880p

switch 문과 같은 기능을 구현함, <otherwise> 태그는 생략 가능

<choose>
    <when test="조건식1">
        구문1
    </when>
    <when test="조건식2">
        구문2
    </when>
    ...
    <otherwise>
        구문 n+1
    </otherwise>
</choose>

 

3. <foreach> 태그로 회원 정보 조회하기

881p

<foreach item=""item" collection="list" index="index" open=" (" close=")" separator=",">
    #{item}
</foreach>
속성 설명
collection 전달받은 인자 값을 의미함. 배열과 List 계열 인스턴스를 전달할 수 있음
List 인스턴스 전달 시 list로 표시하고, 배열 전달 시에는 array로 표시함
index foreach문이 반복될 때마다 1씩 증가시키면서 접근하는 값의 위치를 나타냄.
최초 값의 위치는 0임
item 반복문이 실행될 때마다 collection 속성에 지정된 값에 접근하여 차례대로 사용함
open 해당 구문이 시작될 때 지정한 기호를 추가함
close 해당 구문이 끝날 때에 지정한 기호를 추가함
separator 한 번 이상 반복될 때 반복되는 사이에 지정한 기호를 추가함

* SQL문에 List 인스턴스나 배열을 전달하면 자동으로 Map에 전달되어 이름을 key로 사용함 (parameterType="java.util.Map")

List 인스턴스는 list를 키로 사용하고, 배열은 array를 키로 사용함

 

예)

...

select * from t_member

where name in

<foreach item="item" collection="list" open="(" separator="," close=")" >

  #{item}

</foreach>

order by joinDate desc

...

=>

전달된 List = {"홍길동", "차범근", "이순신"} 

select * from t_member

where name in ('홍길동','차범근','이순신')

 

4. <foreach> 태그로 회원 정보 추가하기

884p

오라클에서는 insert문을 반복해서 연달아 사용하면 오류 발생함

=> insert문에서 values 안에 <foreach>문을 넣어서 사용하지 않고 insert all into 형식으로 사용함

 

* 여러 개의 테이블에 여러 건의 데이터 한번에 삽입하기

INSERT ALL

INTO 테이블1(컬럼1, 2, 3, 4) VALUES (값1, 2, 3, 4)

INTO 테이블2(컬럼1, 2, 3) VALUES (값1, 2, 3)

...

SELECT * FROM DUAL <<  SELECT 절이 마지막에 필수로 작성되어야 함

 

<insert id="foreachInsert" parameterType="java.util.Map">
    <foreach item="item" collection="list" open="INSERT ALL" separator=" " close="SELECT * FROM DUAL">
        INTO t_member(id, pwd, name, email)
        VALUES (#{item.id}, #{item.pwd}, #{item.name}, #{item.email})
    </foreach>
</insert>

=>

INSERT ALL

INTO t_member (~~~) 

VALUES (~~~)

INTO t_member(~~~)

VALUES (~~~)

...

SELECT * FROM DUAL

 

5. <sql> 태그와 <include> 태그로 SQL문 중복 제거하기

886p

<sql> 태그에 공통으로 사용되는 코드를 작성,

<select> 태그 등의 안에서 공통 코드가 들어갈 부분에 <include refid="sql 태그 아이디" /> 를 작성하면 공통 SQL문을 재사용할 수 있음

 

<sql id="a">

  공통SQL코드

</sql>

<select ...>

  <include refid="a" />

  나머지 코드

</select>

 

* 마이바티스에서 오라클을 연동해 like 검색하는 방법

% 기호와 조건값 사이에 반드시 || 기호를 사용해서 연결해주어야 함

 예)

WHERE name like '%'#{name}'%' (x)

WHERE name like '%' || #{name} || '%' (o)