MyBatis 학습 일지

DB의 정보를 읽어내는 SQL을 작성하고 관리하는 데에 있어 그 복잡함을 줄이고자 MyBatis를 학습했다. 그 기록을 이 공간에 남겨둔다.

 

Mapper 설정부터.

MyBatis는 두 가지 xml 파일을 참조한다.

하나는 Mybatis Configuration File이고, 다른 하나는 SQL Mapper 파일이다.

SQL Mapper 파일을 이용해서 자바 파일과 SQL문을 분리할 수 있다.

 

SQL Mapper

MyBatis를 사용하는 주된 목적은 프로그램 코드와 SQL 문을 분리하여 유지보수의 용이성을 높이는 것이다.

여기서 SQL문을 저장하는 공간이 SQL Mapper 파일이며, DAO 객체는 SqlSession 객체가 SQL Mapper 파일을 참조하여 필요한 SQL문을 얻어낸 뒤, 해당 SQL문을 가지고 Data에 Access 하는 방식으로 동작하게 된다.

그 예제도 한번 살펴보자.

<?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 namespace="BoardDAO">
    <insert id="insertBoard">
        insert into BOARD (title, writer, content)
        values (#{title}, #{writer}, #{content})
    </insert>
 ...
</mapper>

 

위 예제에 대해 부가적인 설명을 하자면 다음과 같다.

1. XML과 DTD 선언

SQL Mapper 파일은 XML 파일이기 때문에 가장 먼저 XML 선언이 위치하게 되고, 해당 xml 파일의 유효성을 체크하기 위한 dtd 선언이 뒤따른다.

<?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">

 

2. Root Element - <Mapper>

SQL Mapper 파일은 root element인 <mapper>를 작성하는 것으로 시작한다.

<mapper>의 namespace 속성은 java의 package처럼 여러 개의 SQL문을 하나로 그룹화 하기 위한 용도로 활용한다.

SQL Mapper 파일에 작성하는 모든 SQL문은 <Mapper> 하위에 위치해야 한다.

<mapper namespace="BoardDAO">

 

3. select, insert, update, delete

SQL문에는 SELECT, INSERT, UPDATE, DELETE라는 명령어가 있는데, 이에 각각 대응하는 것이

<SELECT>, <INSERT>, <UPDATE>, <DELETE> 이다.

이 때, 명령어 태그 옆에 붙는 attributes들이 있는데, 하나씩 설명하자면 다음과 같다.

속성(attribute) 내용
id 각 SQL문을 구분하기 위한 용도로 쓰인다.
고유값이어야 한다.
resultType SELECT문의 실행 결과를 담는 객체이다.
패키지 이름을 포함한 class를 넣거나
객체의 alias를 지정하면 된다.
resultMap SELECT문 실행결과를 담는 객체를 resultMap으로 지정한다.
<resultMap>을 별도로 선언해주어야 하고,
resultType과 resultMap 중 하나를 결정해서 사용해야 한다.
parameterType 지정한 객체의 property값이 SQL문의 입력 parameter로 지정된다.

 

예제)

<select>
    select * from BOARD order by seq desc
</select>
<insert id="insertBoard">
    insert into BOARD (title, writer, content)
    values (#{title}, #{writer}, #{content})
</insert>
<update id="updateBoard">
    update BOARD
    set title=#{title}, content=#{content} where seq=#{seq}
</update>
<delete id="deleteBoard">
    delete from BOARD where seq=#{seq}
</delete>

 

resultType 보충 설명

resultType은 SELECT문에 대한 실행결과를 담을 객체라고 했다.

패키지 이름을 포함한 전체 클래스 명을 지정하거나 객체의 alias를 지정하여 사용할 수 있다.

여기서 alias는 MyBatis 설정 파일에서 지정해줄 수 있다.

 

예를 들어 다음 두 예제는 동일한 동작을 나타내고 있다.

<!-- 클래스의 path 다 지정한 경우 -->
<select id="selectList" resultType="com.sample.example.vo.Project">
    SELECT name, age
    FROM PROJECTS
    ORDER BY id DESC
</select>

 

Alias 지정하는 예제

<!-- Mybatis 설정 파일에서 alias 지정. -->
<typeAliases>
    <typeAlias type="com.sample.example.vo.Project" alias="project" />
</typeAliases>

<!-- SQL Mapper File -->
<select id="selectList" resultMap="project">
    SELECT name, age
    FROM PROJECTS
    ORDER BY id DESC
</select>

 

위의 예제에서 MyBatis는 겨로가를 저장하기 위해 resultType으로 호출된 VO(또는 DTO) 의 인스턴스를 생성하고,

읽어들인 Column에 대응하는 setter를 호출한다.

예를 들어 위의 예제에서 SELECT name, age 라고 했으므로

Project.VO 에 대해서는 해당 파일에 작성되어 있는 setName(), setAge()를 호출할 것이다.

 

SQL Mapper 파일은 MyBatis 설정 파일에 등록함으로써 마무리.

우리가 작성한 SQL Mapper 파일은 MyBatis가 인식할 수 있도록 SQL Mapper 파일이 위치한 MyBatis 설정 파일에 등록해주어야 한다.

ex)

<mappers>
    <mapper resource="mappings/board/-mapping.xml">
</mappers>

Select, Insert, Update, Delete에 대한 더 구체적인 예제

 

Select

위에서 설명했듯 SELECT 구문은 MyBatis에서 가장 흔하게 사용되는 명령어다. SELECT는 MyBatis에서 주로 데이터를 조회하고 그 결과를 매핑(우리가 설정한 VO나 DTO 형식에 맞추어 넣음)하는 데에 집중하고 있다.

 

<select id="selectPerson" parameterType="int" resultType="hashmap">
    SELECT * FROM PERSON WHERE ID = #{id}
</select>

위 구문은 selectPerson이라는 id를 갖고, int 타입의 파라미터를 받는다. 그리고 그 결과 데이터는 resultType인 hashMap에 저장된다.

 

image

parameter 속성. - 출처: https://mybatis.org/mybatis-3/ko/sqlmap-xml.html#select

 

insert

insert는 DB table에 특정 데이터를 넣을 때 사용한다.

특히 insert는 몇 가지 추가적인 속성을 갖는데, useGeneratedKey와 keyProperty가 대표적인 예이다.

useGeneratedKey는 테이블의 특정 필드가 autoIncrement속성을 갖는 경우 사용할 수 있다. (자동으로 1씩 증가.)

keyProperty에는 useGeneratedKey를 사용할 대상 필드를 입력하면 된다.

 

예제)

<insert id="insertAuthor" useGeneratedKeys="true" keyProperty="id">
  insert into Author (username,password,email,bio)
  values (#{username},#{password},#{email},#{bio})
</insert>

 

또한 MyBatis에서는 다중 레코드 입력을 지원하는데, 이 경우 forEach를 사용하면 된다.

<insert id="insertAuthor" useGeneratedKeys="true"
    keyProperty="id">
  insert into Author (username, password, email, bio) values
  <foreach item="item" collection="list" separator=",">
    (#{item.username}, #{item.password}, #{item.email}, #{item.bio})
  </foreach>
</insert>

 

update, delete

수정 및 삭제 작업도 Insert와 비슷하게 사용된다.

예제는 다음과 같으며, 그 아래에 Insert, Update, Delete의 properties를 첨부한다.

 

<update id="updateAuthor">
  update Author set
    username = #{username},
    password = #{password},
    email = #{email},
    bio = #{bio}
  where id = #{id}
</update>

<delete id="deleteAuthor">
  delete from Author where id = #{id}
</delete>

 

image2

여기까지 MyBatis의 Select, Insert, Update, Delete의 간단한 예제를 보았는데, 실제로 자주 쓰는 코드는 무엇인지 더 살펴보자.

 

Parameters

#{id} 와 같이 MyBatis 구문에 특이하게 생긴 녀석들을 위 예제들에서 자주 볼 수 있었을 것이다.

Paramters는 마이바티스에서 매우 중요한 엘리먼트이다.

 

이러한 파라미터는 paramterType을 지정해주어야 하는 경우와 그렇지 않은 경우로 나뉘는데, 다음 예제들에서 차이점을 보여주겠다:

 

<select id="selectUsers" resultType="User">
  select id, username, password
  from users
  where id = #{id}
</select>

먼저 위 예제의 경우 파라미터는 id 하나라는 점, 그리고 그것의 type은 int로 (DB에) 설정되어 있다는 점에 의해 따로 parameterType을 지정해주지 않았다.

왜냐하면 Integer와 String과 같은 Primitive 타입은 프로퍼티를 명시해주지 않아도 들어온 값 그대로 #{id} 부분을 대체하기 때문이다.

 

반면에 아래와 같이 id, username, password를 가지는 복잡한 객체를 전달할 것이라면 parameterType을 명시해주어야 한다.

<insert id="insertUser" parameterType="User">
  insert into users (id, username, password)
  values (#{id}, #{username}, #{password})
</insert>

 

ResultType

resultMap은 마이바티스에서 가장 중요한 요소이다. ResultSet에서 데이터를 가져올 때 작성되는 JDBC 코드의 대부분을 줄여주는 역할을 한다.

SQL의 join과 같은 요소는 코드를 굉장히 길어지게 만들 수 있다.

이 경우 ResultMap을 이용하면 복잡한 구문을 줄일 수 있다.

 

예를 들어 다음과 같은 VO가 있다고 하자.

package com.someapp.model;
public class User {
  private int id;
  private String username;
  private String hashedPassword;

  public int getId() {
    return id;
  }
  public void setId(int id) {
    this.id = id;
  }
  public String getUsername() {
    return username;
  }
  public void setUsername(String username) {
    this.username = username;
  }
  public String getHashedPassword() {
    return hashedPassword;
  }
  public void setHashedPassword(String hashedPassword) {
    this.hashedPassword = hashedPassword;
  }
}

 

이 경우 some_table이라는 table의 column이 User 객체의 필드, 그러니까 id, username, hashedPassword 를 가진다고 할 때

매우 쉽게 ResultSet에 매핑할 수 있다.

<select id="selectUsers" resultType="com.someapp.model.User">
  select id, username, hashedPassword
  from some_table
  where id = #{id}
</select>

 

TypeAlias를 이용하면 더 많이 줄일 수 있다.

위에서도 한 번 언급했지만 다시 한 번 강조삼아 설명하자면

<!-- XML설정파일에서 -->
<typeAlias type="com.someapp.model.User" alias="User"/>

<!-- SQL매핑 XML파일에서 -->
<select id="selectUsers" resultType="User">
  select id, username, hashedPassword
  from some_table
  where id = #{id}
</select>

이렇게 쓸 수 있다.

 

resultType을 쓰려는데 Table의 Column명과 VO의 필드명이 다른 경우

resultType을 쓰려는데 Table의 Column명과 VO의 필드명이 다른 경우가 있을 수 있다.

예를 들어 내 VO는 id, username, hashedPassword라는 필드를 갖지만

DB에는 user_id, user_name, hashed_password라는 필드로 되어 있을 수 있다.

이 경우 마이바티스에서는 SQL 구문에 별칭을 지정하여 원하는 이름으로 데이터를 뽑아낼 수 있다.

 

<select id="selectUsers" resultType="User">
  select
    user_id             as "id",
    user_name           as "userName",
    hashed_password     as "hashedPassword"
  from some_table
  where id = #{id}
</select>

 

전자정부프레임워크에서의 예제

먼저 전자정부프레임워크 웹 프로젝트를 실행시키면 localhost:8080/project명/ 으로 들어가고,

이것은 자동적으로 src/main/webapp의 index.jsp를 찾는다.

example 속 index.jsp는 /egovSampleList.do 로 forward시키는데,

이 때 src/main/java 밑의 egovframework.example.sample.web 패키지의 EgovSampleController.java 라는 클래스를 살펴보면

가장 첫 번째 메서드인 selectSampleList위에 적혀 있는 @RequestMapping의 value가 forward된 주소와 같다는 것을 알 수 있다.

해당 메서드는 "sample/egovSampleList"라는 String을 return하는데,

이것은 src/main/webapp/jsp/egovframework/sample/egovSampleList.jsp라는 파일로 연결된다.

왜 sample 앞에 src~ 이하는 없는지 알아보면 src/main/webapp/WEB-INF/config/egovframework/springmvc 밑의 dispatcher-servlet.xml 파일에

다음 부분에서 그것을 지정해주고 있기 때문이다.(prefix, suffix)

    <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver" p:order="1"
        p:viewClass="org.springframework.web.servlet.view.JstlView"
        p:prefix="/WEB-INF/jsp/egovframework/example/" p:suffix=".jsp"/>

 

대강의 흐름을 알았다면 주어진 sample을 이용해 데이터를 우리가 원하는대로 화면에 그려내보자.

먼저 egovSampleList.jsp 파일을 다음과 같이 수정한다.

<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib prefix="c"      uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form"   uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="ui"     uri="http://egovframework.gov/ctl/ui"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <div id="table">
        <table width="100%" border="0">
            <colgroup>
                <col width="40" />
                <col width="100" />
                <col width="150" />
                <col width="80" />
            </colgroup>
            <tr>
                <th align="center">id</th>
                <th align="center">이름</th>
                <th align="center">내용</th>
                <th align="center">등록자</th>

            </tr>
            <tr>
                <td align="center" ><c:out value="${sample.id}" /> </td>
                <td align="center" style="color:blue"><c:out value="${sample.name}" /> </td>
                <td align="center"><c:out value="${sample.description}" /> </td>
                <td align="center"><c:out value="${sample.regUser}" /> </td>
            </tr>
        </table>
    </div>

</body>
</html>

 

그리고 EgovSampleController.java의 (찾기 힘들다면 ctrl shift R 로 검색)

public String selectSampleList 메서드를 아래와 같이 고쳐보자.

    @RequestMapping(value = "/egovSampleList.do")
    public String selectSampleList(@ModelAttribute("searchVO") SampleDefaultVO searchVO, ModelMap model) throws Exception {

        SampleVO sampleVO = new SampleVO();
        sampleVO.setId("SAMPLE-00015");
        sampleVO.setName("Name of the sample vo)");
        sampleVO.setDescription("description of sample VO");
        sampleVO.setUseYn("Y");
        sampleVO.setRegUser("test user 1");

        SampleVO sample = sampleService.selectSample(sampleVO);
        model.addAttribute("sample", sample);
        return "sample/egovSampleList";
    }

 

위에서는 sampleVO라는 클래스의 인스턴스(객체)를 생성해 id, name, description, useYN, regUser를 설정해주고 있다.

sampleVO에 대해 궁금하다면 직접 찾아서 필드와 getter, setter 메서드를 보고 오자.

그리고 위 코드에서 우리는 sampleService의 selectSample을 호출하는 것을 볼 수 있는데,

sampleService는 sampleServiceImpl.java 파일에서 정의하고,

Impl 파일의 selectSample은 이렇게 생겼다:

    @Override
    public SampleVO selectSample(SampleVO vo) throws Exception {
        SampleVO resultVO = sampleDAO.selectSample(vo);
        if (resultVO == null)
            throw processException("info.nodata.msg");
        return resultVO;
    }

그런데 해당 코드는 MyBatis가 아니라 iBatis를 이용한 예제이므로,

우리는 MyBatis코드로 적절히 고쳐줄 필요가 있다.

 

그래서 Impl 파일 안에

selectSample 메서드(바로 위 예제)를 다음과 같이 고쳐주자.

@Override
public SampleVO selectSample(SampleVO vo) throws Exception {
    SampleVO resultVO = sampleDAOMybatis.selectSample(vo); // 바뀐 부분
    if (resultVO == null)
        throw processException("info.nodata.msg");
    return resultVO;
}

그리고 해당 파일의 맨 위에서 조금만 스크롤을 내리면 보이는 아래 부분을 주석해제해주자( TODO 줄 빼고.)

    // TODO mybatis 사용
//    @Resource(name="sampleMapper")
//    private SampleMapper sampleDAOMybatis;

-> 아래처럼.

// TODO mybatis 사용
@Resource(name="sampleMapper")
private SampleMapper sampleDAOMybatis;

이렇게 해주면 동작은 똑같을지라도 뒷단에서 iBatis를 쓰냐 MyBatis를 쓰느냐의 차이가 발생한다.

 

위에서 sampleDAOMybatis는 데이터 타입이 SampleMapper형이다.

해당 SampleMapper를 열어보면

SampleVO selectSample(SampleVO vo) throws Exception; 이 보인다.

그런데 해당 메서드를 implement하는 파일은 눈을 씻고 찾아봐도 보이지 않는다.

어떻게 된 일일까?

 

그 비밀은 context-mapper.xml 파일에 숨어있다.(src/main/resources/egovframework/spring/context-mapper.xml)

해당 파일에서는 <bean id="sqlSession" class="org.mybatis.spring.SqlSessionFactoryBean">

이라고 하는 녀석 안에 dataSource, configLocation, mapperLocations를 정의하고 있다.

 

context-mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">

    <!-- SqlSession setup for MyBatis Database Layer -->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value="classpath:/egovframework/sqlmap/example/sql-mapper-config.xml" />
        <property name="mapperLocations" value="classpath:/egovframework/sqlmap/example/mappers/*.xml" />
    </bean>

    <!-- MapperConfigurer setup for MyBatis Database Layer with @Mapper("deptMapper") in DeptMapper Interface -->
     <bean class="egovframework.rte.psl.dataaccess.mapper.MapperConfigurer">
        <property name="basePackage" value="egovframework.example.sample.service.impl" />
    </bean>

</beans>

 

마이바티스 공식문서 에 따르면 위 파일의 첫 번째 bean인 SqlSessionFactoryBean은 스프링의 FactoryBean을 구현하고 있고,

애플리케이션 시작 시점에 SqlSessoinFactory를 빌드하여 sqlSessionFactory라는 이름으로 저장한다고 한다.

(여기서 FactoryBean은 예전에 배웠는데 무엇인지 까먹었다.. IoC와 관련이 있는 것 같은데, 더 알아보려면 여기링크에서 확인할 수 있다.)

(당장 알 필요는 없는 것 같다.)

 

아무튼 우리는 sqlSessionFactory Bean의 configLocation property의 value로 지금

classpath:/egovframework/sqlmap/example/sql-mapper-config.xml 을 설정해놓았다.(context-mapper.xml 파일에.)

해당 프로퍼티는 공식문서에 따르면 typeAliases나 settings를 정의하는 데에만 사용한다고 한다.

(실제로 해당 파일은 typeAliases만 정의하고 있다.)

 

그리고 context-mapper.xml 파일 sqlSession Bean의 세 번째 property를 보면 mapperLocations라고 나와 있는데,

이것이 바로 MyBatis의 SQL 태그들이 적혀있는 xml 파일이 어디 있는지 정의하는 곳이다.

그리고 해당 쿼리문들의 id는 Mapper 파일과 연결되는데, 해당 mapper파일의 위치는 context-mapper.xml의 두 번째 bean에 나와 있다.

 

context-mapper.xml 파일 맨 밑에 보면

<bean class="egovframework.rte.psl.dataaccess.mapper.MapperConfigurer">
    <property name="basePackage" value="egovframework.example.sample.service.impl" />
</bean>

이렇게 생긴 녀석이 있는데, 이 부분에 의해 egovframework.example.sample.service.impl 밑에 있는 SampleMapper.java와,

<property name="mapperLocations" value="classpath:/egovframework/sqlmap/example/mappers/*.xml" /> 에서 value에 해당하는 경로에 있는 .xml 파일이 연결되는 것이다.

어떻게 Mapper파일을 Spring이 읽어내는지에 대해서는 Mapper.class에 적힌 주석을 보면 알 수 있다:

Mapper 인터페이스에 대한 marker Annotation(Single-value)으로 MyBatis 적용 방식 중 annotation을 사용한 방식에 대한 기준을 위해 사용된다.

 

실제로 SampleMapper.java 파일에는 @Mapper("sampleMapper") 라는 어노테이션이 달려 있으며, 이것을 통해 Spring이 Mapper 파일을 인식하고 MyBatis 명령어들이 담겨 있는 EgovSample_Sample_SQL.xml 과 연결짓는 것으로 보인다.

 

실행

주저리 주저리 말이 길었는데, 프로젝트를 한번 실행해보면

image

위와 같은 화면이 나올 것이다. (안 되면 내게 말해조!!!)

 

추가 예제

여기까지 했다면 하나쯤은 자신이 만들어볼 생각도 들 만하다. 아닐 수도 있지만.

필자는 이해를 확실히 하기 위해 하나 더 예제를 만들어 실행해보았다.

일단 무엇 무엇을 추가했는지 적어둘테니 하나씩 파악해보자.

(중간에 오류가 나더라도 가만히 놔뒀다가 다 따라하고 나면 하나씩 import해주자.

import는 빨간줄이 뜨는 곳에 마우스를 갖다 대고 잠시 기다리면 import~~ 라고 뜰 것이다.)

 

패키지: egovframework.example.sample.web

클래스: EgovSampleController.java

...
    @RequestMapping(value = "/egovSampleList.do")
    public String selectSampleList(@ModelAttribute("searchVO") SampleDefaultVO searchVO, ModelMap model) throws Exception {
        SampleVO sampleVO = new SampleVO();
        sampleVO.setId("SAMPLE-00015");
        sampleVO.setName("Name of the sample vo)");
        sampleVO.setDescription("description of sample VO");
        sampleVO.setUseYn("Y");
        sampleVO.setRegUser("test user 1");

        SampleVO sample = sampleService.selectSample(sampleVO);
        model.addAttribute("sample", sample);


        TestVO testVO = new TestVO();
        testVO.setId("SAMPLE-00017");

        TestVO test = sampleService.selectJustIdName(testVO);
        model.addAttribute("test", test);

        return "sample/egovSampleList";
    }
...

 

패키지: egovframework.example.sample.service.EgovSampleService

클래스: EgovSampleService.java

public interface EgovSampleService {

    //    아래 한 줄 추가.
       TestVO selectJustIdName(TestVO vo) throws Exception;


    ...

}

 

패키지: egovframework.example.sample.service.EgovSampleService

클래스: TestVO.java (새로 추가.)

package egovframework.example.sample.service;

public class TestVO {
    private String id;
    private String name;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

 

패키지: egovframework.example.sample.service.EgovSampleService.impl

클래스: EgovSampleServiceImpl.java

// public SampleVO selectSample(SampleVO vo) throws Exception 메서드 밑에 추가.
    @Override
    public TestVO selectJustIdName(TestVO vo) throws Exception {
        TestVO resultVO = sampleDAOMybatis.selectJustIdName(vo);
        if (resultVO == null)
            throw processException("info.nodata.msg");
        return resultVO;
    }

 

패키지: egovframework.example.sample.service.EgovSampleService.impl

클래스: SampleMapper.java

@Mapper("sampleMapper")
public interface SampleMapper {
    // 아래 한 줄 추가.
    TestVO selectJustIdName(TestVO vo) throws Exception;

...    

 

패키지: src/main/resources/

클래스: egovframework/sqlmap/example/mappers/EgovSample_Sample_SQL.xml

// <select id="selectSample" resultMap="sample"> ~ </select> 구문 밑에 추가.

<select id="selectJustIdName" resultType="testVO">
    SELECT
        ID, NAME
    FROM SAMPLE
    WHERE ID=#{id}
</select>

 

패키지: src/main/resources/

클래스: egovframework/sqlmap/example/sql-mapper-config.xml

<configuration>
    <typeAliases>
        ...
        <!-- 아래 한 줄만 추가 -->
        <typeAlias alias="testVO" type="egovframework.example.sample.service.TestVO" /> 
    </typeAliases>
</configuration>

 

위치: src/main/webapp/WEB-INF/jsp/egovframework/example/sample/egovSampleList.jsp

아래와 같이 변경

<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib prefix="c"      uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form"   uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="ui"     uri="http://egovframework.gov/ctl/ui"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <div id="table">
        <table width="100%" border="0">
            <colgroup>
                <col width="40" />
                <col width="100" />
                <col width="150" />
                <col width="80" />
            </colgroup>
            <tr>
                <th align="center">id</th>
                <th align="center">이름</th>
                <th align="center">내용</th>
                <th align="center">등록자</th>

            </tr>
            <tr>
                <td align="center" ><c:out value="${sample.id}" /> </td>
                <td align="center" style="color:blue"><c:out value="${sample.name}" /> </td>
                <td align="center"><c:out value="${sample.description}" /> </td>
                <td align="center"><c:out value="${sample.regUser}" /> </td>
            </tr>
            <tr>
                <td align="center" ><c:out value="${test.id}" /> </td>
                <td align="center" style="color:blue"><c:out value="${test.name}" /> </td>
            </tr>
        </table>
    </div>

</body>
</html>

 

결과.

 

ref.

https://mybatis.org/mybatis-3/ko/sqlmap-xml.html

https://linux.systemv.pe.kr/mybatis%EC%97%90-dao-%EC%99%80-mapper/

https://juyoungit.tistory.com/306

https://wjheo.tistory.com/entry/%EC%8A%A4%ED%94%84%EB%A7%81MyBatisMySQL-%EC%97%B0%EB%8F%99-%EB%B0%8F-%ED%85%8C%EC%8A%A4%ED%8A%B8DAO-3%EB%8B%A8-%EA%B5%AC%EC%A1%B0%EB%A1%9C-%EA%B5%AC%ED%98%84

https://mybatis.org/spring/ko/factorybean.html

'Knowwheresoft' 카테고리의 다른 글

MyBatis + 전자정부프레임워크 생기초  (0) 2021.08.09
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기

댓글을 달아 주세요

">