쭈쌤
쭈쌤 Hello World

[Java] 자바 콘솔 프로그램에서 MyBatis 연동

크리에이티브 커먼즈 라이선스 ITPAPER(호쌤,쭈쌤)에 의해 작성된 ≪[Java] 자바 콘솔 프로그램에서 MyBatis 연동≫은(는) 크리에이티브 커먼즈 저작자표시-비영리-동일조건변경허락 4.0 국제 라이선스에 따라 이용할 수 있습니다.
이 라이선스의 범위 이외의 이용허락을 얻기 위해서는 leekh4232@gmail.com으로 문의하십시오.

[Java] 자바 콘솔 프로그램에서 MyBatis 연동

MyBatis란 객체지향 언어인 자바의 관계형 데이터 베이스 프로그래밍을 좀더 쉽게 할수 있도록 도와주는 프레임워크입니다.

Framework

뼈대근간을 이루는 코드들의 묶음.

프로그램의 기본 흐름이나 구조를 미리 정해놓고, 이 구조에 자신의 코드를 추가하는 방식으로 개발할 수 있도록 하는 프로그래밍의 기본 틀을 의미.

개발에 필요한 구조가 사전에 제공(대체로 다운로드 받을 수 있다)되고, 여기에 필요한 부분을 개발자가 구현해서 조립하는 형태로 개발이 진행된다.

Framework를 사용할 경우 장점

  • 개발 기간을 단축할 수 있다.
  • 팀 안에서 개인의 능력 차이를 극복하고 일정한 품질을 보장할 수 있다.

#01. 환경설정

1) 라이브러리 설정

다음의 항목들을 Eclipse의 Java Build Path에 설정한다.

2) 설정파일 구성

study.java.mybatis 패키지를 생성하고 그 안에 mybatis_config.xml 파일을 생성한다.

패키지 이름과 파일명은 임의로 변경 가능하다.

mybatis_config.xml

https://mybatis.org/mybatis-3/ko/getting-started.html에서 설정파일의 기본 원형을 가져와 생성한 mybatis_config.xml에 적용한다.

before

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?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>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="${driver}" />
                <property name="url" value="${url}" />
                <property name="username" value="${username}" />
                <property name="password" value="${password}" />
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="org/mybatis/example/BlogMapper.xml" />
    </mappers>
</configuration>

after

${driver} 라고 된 위치에 MySQL JDBC 8의 driver 이름인 com.mysql.cj.jdbc.Driver을 적용한다.

${url}로 된 위치는 아래와 같은 형식의 접속 문자열을 구성해야 한다.

1
jdbc:mysql://localhost:3306/myschool?characterEncoding=UTF8&amp;serverTimezone=UTC

localhost(host이름), 3306(포트번호), myschool(db이름)을 각각 별도의 변수로 사용하기 위해 다음과 같이 URL을 구성

1
jdbc:mysql://${hostname}:${portnumber}/${database}?characterEncoding=UTF8&amp;serverTimezone=UTC

<mappers> 태그에 속한 항목들은 일단 삭제한다.

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
<?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>
    <!-- MySQL 접속 정보를 지정한다. -->
    <properties>
        <property name="hostname" value="호스트이름" />
        <property name="portnumber" value="포트번호" />
        <property name="database" value="DB이름" />
        <property name="username" value="사용자계정" />
        <property name="password" value="계정비밀번호" />
    </properties>

    <!-- MySQL 접속 객체 구성 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://${hostname}:${portnumber}/${database}?characterEncoding=UTF8&amp;serverTimezone=UTC" />
                <property name="username" value="${username}" />
                <property name="password" value="${password}" />
            </dataSource>
        </environment>
    </environments>

    <!-- 실행할 SQL문을 정의한 Mapper XML의 경로를 지정한다. -->
    <mappers>
        <!--
             이 위치에서 다음의 형식으로 Mapper 파일의 경로를 지정한다.
             <mapper resource="Mapper 파일 경로" />
        -->
    </mappers>
</configuration>

3) MyBatis 설정 파일을 로드하는 클래스 정의

아래 소스코드에서 패키지 이름과 mybatis_config.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
40
41
package study.java.mybatis;

import java.io.IOException;
import java.io.Reader;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MyBatisConnectionFactory {
    /** 데이터베이스 접속 객체 */
    // import org.apache.ibatis.session.SqlSessionFactory;
    private static SqlSessionFactory sqlSessionFactory;

    /** XML에 명시된 접속 정보를 읽어들인다. */
    // 클래스 초기화 블럭 : 클래스 변수의 복잡한 초기화에 사용된다.
    // 클래스가 처음 로딩될 때 한번만 수행된다.
    static {
        // 접속 정보를 명시하고 있는 XML의 경로 읽기
        // --> import java.io.Reader;
        // --> import org.apache.ibatis.io.Resources;
        try {
            // mybatis_config.xml 파일의 경로 지정
            Reader reader = Resources.getResourceAsReader("study/java/mybatis/mybatis_config.xml");

            // sqlSessionFactory가 존재하지 않는다면 생성한다.
            if (sqlSessionFactory == null) {
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /** 데이터베이스 접속 객체를 통해 DATABASE에 접속한 세션를 리턴한다. */
    // --> import org.apache.ibatis.session.SqlSession;
    public static SqlSession getSqlSession() {
        return sqlSessionFactory.openSession();
    }
}

#02. 데이터 조회 결과가 저장될 자료구조 정의

study.java.model 패키지를 추가하고 그 안에 테이블단위 혹은 Join문이 구성되는 단위마다 Beans 클래스를 정의한다.

MyBatis를 위한 클래스에서는 생성자를 정의할 필요가 없다. 값의 할당은 setter 메서드를 사용한다.

1
2
3
4
5
6
7
8
9
package study.java.model;

public class Department {
    private int deptno;
    private String dname;
    private String loc;

    /** getter, setter, toString 정의 **/
}

03. Mapper XML 정의

1) mybatis_config.xml 파일에 생성할 Mapper 경로 정의

<mappers> 태그 안에 생성할 파일의 경로를 명시해야 한다.

1
2
3
<mappers>
    <mapper resource="study/java/mybatis/mappers/DepartmentMapper.xml" />
</mappers>

2) 명시한 Mapper 파일 생성

study.java.mybatis.mappers 패키지를 만들고 그 안에 Beans이름Mapper.xml 형식으로 파일을 생성한다.

DepartmentMapper.xml

아래의 Mapper 원형 구문을 기본형으로 삼아 사용하되 구현하고자 하는 SQL문의 성격에 따라 추가적으로 <select>, <insert>, <update>, <delete>태그를 추가할 수 있다.

{Beans}라고 명시한 부분은 사용하고자 하는 클래스 이름으로 수정하세요.

각각의 태그가 하나의 DAO 메서드 역할을 하고 id속성값이 메서드 이름이 된다.

SQL문 안에서 parameterType으로 설정된 객체의 멤버변수를 통해 getter 메서드를 호출할 수 있다.

1
SELECT deptno, dname, loc FROM department WHERE deptno=#{deptno}

Mapper 원형

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

    <!-- Beans 클래스의 객체이름(id)과 클래스이름(type)을 명시한다. -->
    <resultMap id="departmentMap" type="study.java.model.Department">
        <!-- Beans의 멤버변수(property)이름과 대상 테이블의 컬럼(column)을 연결한다. -->
        <result property="deptno"   column="deptno" />
        <result property="dname"    column="dname" />
        <result property="loc"      column="loc" />
    </resultMap>

    <!-- 단일행 조회를 위한 기능 정의 -->
    <select id="selectItem"
            parameterType="study.java.model.Department"
            resultMap="departmentMap">
        SELECT deptno, dname, loc FROM department WHERE deptno=#{deptno};
    </select>

    <!-- 다중행 조회를 위한 기능 정의 -->
    <select id="selectList"
            parameterType="study.java.model.Department"
            resultMap="departmentMap">
        SELECT deptno, dname, loc FROM department ORDER BY deptno ASC;
    </select>

    <!-- 데이터 수 조회를 위한 기능 정의 -->
    <select id="selectCount"
            parameterType="study.java.model.Department"
            resultType="int">
        SELECT COUNT(*) FROM department;
    </select>

    <!-- 데이터 저장을 위한 기능 정의 -->
    <insert id="insertItem"
            parameterType="study.java.model.Department"
            useGeneratedKeys="true"
            keyProperty="deptno">
        INSERT INTO department (
            dname, loc
        ) VALUES (
            #{dname}, #{loc}
        );
    </insert>

    <!-- 데이터 삭제를 위한 기능 정의 -->
    <delete id="deleteItem" parameterType="study.java.model.Department">
        DELETE FROM department WHERE deptno=#{deptno};
    </delete>

    <!-- 데이터 갱신을 위한 기능 정의 -->
    <update id="updateItem" parameterType="study.java.model.Department">
        UPDATE department SET
            dname=#{dname},
            loc=#{loc}
        WHERE deptno=#{deptno};
    </update>

</mapper>

Department 클래스에 대한 Mapper 완성 예시

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

    <!-- Beans 클래스의 객체이름(id)과 클래스이름(type)을 명시한다. -->
    <resultMap id="departmentMap" type="study.java.model.Department">
        <!-- Beans의 멤버변수(property)이름과 대상 테이블의 컬럼(column)을 연결한다. -->
        <result property="deptno"   column="deptno" />
        <result property="dname"    column="dname" />
        <result property="loc"      column="loc" />
    </resultMap>

    <!-- 단일행 조회를 위한 기능 정의 -->
    <select id="selectItem"
            parameterType="study.java.model.Department"
            resultMap="departmentMap">
        SELECT deptno, dname, loc FROM department WHERE deptno=#{deptno};
    </select>

    <!-- 다중행 조회를 위한 기능 정의 -->
    <select id="selectList"
            parameterType="study.java.model.Department"
            resultMap="departmentMap">
        SELECT deptno, dname, loc FROM department ORDER BY deptno ASC;
    </select>

    <!-- 데이터 수 조회를 위한 기능 정의 -->
    <select id="selectCount"
            parameterType="study.java.model.Department"
            resultType="int">
        SELECT COUNT(*) FROM department;
    </select>

    <!-- 데이터 저장을 위한 기능 정의 -->
    <insert id="insertItem"
            parameterType="study.java.model.Department"
            useGeneratedKeys="true"
            keyProperty="deptno">
        INSERT INTO department (
            dname, loc
        ) VALUES (
            #{dname}, #{loc}
        );
    </insert>

    <!-- 데이터 삭제를 위한 기능 정의 -->
    <delete id="deleteItem" parameterType="study.java.model.Department">
        DELETE FROM department WHERE deptno=#{deptno};
    </delete>

    <!-- 데이터 갱신을 위한 기능 정의 -->
    <update id="updateItem" parameterType="study.java.model.Department">
        UPDATE department SET
            dname=#{dname},
            loc=#{loc}
        WHERE deptno=#{deptno};
    </update>

</mapper>

#04. Java Code에서의 호출

Mapper XML의 namespace 속성이 DepartmentMapper인 경우.

1) 단일행 조회

DepartmentSelectOne.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
import org.apache.ibatis.session.SqlSession;

import study.java.mybatis.MyBatisConnectionFactory;
import study.java.model.Department;

public class SelectOne {
    public static void main(String[] args) {
        // 1) 데이터베이스 접속
        SqlSession sqlSession = MyBatisConnectionFactory.getSqlSession();

        // 2) 조회할 데이터 (null로 사용할 값은 설정하지 않는다)
        Department input = new Department();
        input.setDeptno(102);

        // 3) 데이터 조회
        Department output = sqlSession.selectOne("DepartmentMapper.selectItem", input);

        // 4) 결과 판별
        if (output == null) {
            System.out.println("조회결과 없음");
        } else {
            System.out.println(output.toString());
        }

        // 5) DB 접속 해제
        sqlSession.close();
    }
}
출력결과
1
Department(deptno=102, dname=멀티미디어학과, loc=2호관)

2) 다중행 조회

DepartmentSelectList.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
import java.util.List;

import org.apache.ibatis.session.SqlSession;

import study.java.model.Department;
import study.java.mybatis.MyBatisConnectionFactory;

public class DepartmentSelectList {
    public static void main(String[] args) {
        // 1) 데이터베이스 접속
        SqlSession sqlSession = MyBatisConnectionFactory.getSqlSession();

        // 2) 데이터 조회
        // --> Mapper에서 변수를 사용하고 있지 않기 때문에 파라미터를 전달할 필요가 없다.
        List<Department> output = sqlSession.selectList("DepartmentMapper.selectList", null);

        // 4) 결과 판별
        if (output == null) {
            System.out.println("조회결과 없음");
        } else {
            for (Department item: output) {
                System.out.println(item.toString());
            }
        }

        // 5) DB 접속 해제
        sqlSession.close();
    }
}
출력결과
1
2
3
4
Department(deptno=101, dname=컴퓨터공학과, loc=1호관)
Department(deptno=102, dname=멀티미디어학과, loc=2호관)
Department(deptno=201, dname=전자공학과, loc=3호관)
Department(deptno=202, dname=기계공학과, loc=4호관)

3) 집계함수 조회

DepartmentSelectCount.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import org.apache.ibatis.session.SqlSession;

import study.java.mybatis.MyBatisConnectionFactory;

public class DepartmentSelectCount {
    public static void main(String[] args) {
        // 1) 데이터베이스 접속
        SqlSession sqlSession = MyBatisConnectionFactory.getSqlSession();

        // 2) 데이터 조회
        int count = sqlSession.selectOne("DepartmentMapper.selectCount", null);

        // 4) 결과 판별
        System.out.println(count + "개의 데이터 있음");

        // 5) DB 접속 해제
        sqlSession.close();
    }
}
출력결과
1
4개의 데이터 있음

4) 데이터 저장하기

DepartmentInsert.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
import org.apache.ibatis.session.SqlSession;

import study.java.model.Department;
import study.java.mybatis.MyBatisConnectionFactory;

public class DepartmentInsert {
    public static void main(String[] args) {
        // 1) 데이터베이스 접속
        SqlSession sqlSession = MyBatisConnectionFactory.getSqlSession();

        // 2) 저장할 데이터 준비
        Department input = new Department();
        input.setDname("JAVA학과");
        input.setLoc("공학관");

        // 3) 데이터 저장 --> 리턴값은 저장된 행의 수
        int output = sqlSession.insert("DepartmentMapper.insertItem", input);

        // 4) 결과 판별
        System.out.println(output + "개의 데이터 저장됨");

        // 신규로 저장된 데이터의 PK는 입력 파라미터로 전달된 Beans에 저장된다.
        System.out.println("생성된 PK값: " + input.getDeptno());

        // 5) 변경사항 저장 및 DB 접속 해제
        sqlSession.commit();
        sqlSession.close();
    }
}
출력결과
1
2
1개의 데이터 저장됨
생성된 PK값: 1403

5) 데이터 수정하기

DepartmentUpdate.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
import org.apache.ibatis.session.SqlSession;

import study.java.model.Department;
import study.java.mybatis.MyBatisConnectionFactory;

public class DepartmentUpdate {
    public static void main(String[] args) {
        // 1) 데이터베이스 접속
        SqlSession sqlSession = MyBatisConnectionFactory.getSqlSession();

        // 2) 변경할 데이터 준비
        Department input = new Department();
        input.setDeptno(101);
        input.setDname("수정된학과");
        input.setLoc("수정된위치");

        // 3) 데이터 수정 --> 리턴값은 수정된 행의 수
        int output = sqlSession.update("DepartmentMapper.updateItem", input);

        // 4) 결과 판별
        System.out.println(output + "개의 데이터 수정됨");

        // 5) 변경사항 저장 및 DB 접속 해제
        sqlSession.commit();
        sqlSession.close();
    }
}
출력결과
1
1개의 데이터 수정됨

6) 데이터 삭제하기

DepartmentDelete.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
import org.apache.ibatis.session.SqlSession;

import study.java.model.Department;
import study.java.mybatis.MyBatisConnectionFactory;

public class DepartmentDelete {
    public static void main(String[] args) {
        // 1) 데이터베이스 접속
        SqlSession sqlSession = MyBatisConnectionFactory.getSqlSession();

        // 2) 삭제할 데이터의 조건값 준비
        Department input = new Department();
        input.setDeptno(203);

        // 3) 데이터 삭제 --> 리턴값은 삭제된 행의 수
        int output = sqlSession.delete("DepartmentMapper.deleteItem", input);

        // 4) 결과 판별
        System.out.println(output + "개의 데이터 삭제됨");

        // 5) 변경사항 저장 및 DB 접속 해제
        sqlSession.commit();
        sqlSession.close();
    }
}
출력결과
1
1개의 데이터 삭제됨
Rating:

크리에이티브 커먼즈 라이선스 ITPAPER(호쌤,쭈쌤)에 의해 작성된 ≪[Java] 자바 콘솔 프로그램에서 MyBatis 연동≫은(는) 크리에이티브 커먼즈 저작자표시-비영리-동일조건변경허락 4.0 국제 라이선스에 따라 이용할 수 있습니다.
이 라이선스의 범위 이외의 이용허락을 얻기 위해서는 leekh4232@gmail.com으로 문의하십시오.

comments powered by Disqus