본문 바로가기
JAVA

[JAVA] MyBatis 시작하기

by Amy IT 2022. 6. 15.

 

 

 

▶ MyBatis 란?

 

MyBatis(마이바티스)는 SQL 매핑(mapping) 프레임워크입니다. MyBatis는 자바와 데이터베이스를 연동하기 위해 JDBC로 처리하는 상당 부분의 코드와 파라미터 설정 및 결과 매핑을 대신해 줌으로써, 개발자가 복잡한 코드 작업을 피하고 좀 더 빠르게 SQL을 처리할 수 있도록 도와줍니다. JDBC의 기본적인 프로그래밍 구조와 비교했을 때 MyBatis의 장점은 다음과 같습니다. 

 

JDBC 프로그램 MyBatis
- Connection 직접 맺고 close()

- PreparedStatement 직접 생성

- PreparedStatement의 setXXX() 등 복잡한 작업 직접 처리

- ResultSet 직접 처리
- MyBatis 내부적으로 Connection 맺고 close()

- MyBatis 내부적으로 PreparedStatement 생성

- MyBatis 내부적으로 자동 처리

- 자동으로 객체 생성 및 ResultSet 처리

 

 

 

▶ MyBatis 환경설정

 

1.  드라이버 파일을 클래스 패스에 설정

 

MyBatis를 이용한 DB 연동을 위해서 두 가지 드라이버 파일을 클래스 패스에 설정해야 합니다. 첫째는 MyBatis사에서 제공하는 mybatis-x.x.x.jar 파일이고, 둘째는 사용할 DBMS의 드라이버 파일입니다. 

 

MyBatis 드라이버 파일은 여기서 다운받을 수 있습니다. 

https://github.com/mybatis/mybatis-3/releases

 

저는 오라클 DBMS를 사용하겠습니다. 오라클 드라이버 파일은 오라클을 설치한 경우 자동으로 함께 설치됩니다. 오라클 11g xe 버전의 경우 다음의 경로에 ojdbc6_g.jar 파일명으로 제공됩니다.

C:\oraclexe\app\oracle\product\11.2.0\server\jdbc\lib

 

클래스 패스를 설정하는 여러 방법이 있지만, 저는 프로젝트 생성시 외부 라이브러리로 추가하는 방법을 이용해 보겠습니다. 프로젝트를 생성 후 우클릭하여 다음의 경로로 두 가지 드라이버 파일을 모두 추가해 줍니다.

Build Path - Configure Build Path - Libraries - Add External JARs - 드라이버 선택 - Apply and Close

 

두 가지 드라이버 파일이 추가된 것을 확인할 수 있습니다.

 

 

 

2. XML 설정 파일 만들기

 

(1) Configuration.xml

 

DB 연동에 필요한 정보와 매핑 파일의 경로를 지정하는 환경설정 파일입니다. MyBatis의 공식 홈페이지(https://mybatis.org/mybatis-3/ko/getting-started.html)에서 설정 파일의 기본적인 구조를 가져올 수 있습니다. 프로젝트의 src 폴더에 새 파일을 생성한 후 기본 구조를 활용해 필요한 정보들을 지정합니다. 오라클 11g xe 버전 scott/tiger 계정에 접속하기 위해 다음과 같이 설정할 수 있습니다. 

<?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="oracle.jdbc.driver.OracleDriver" />
        <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" />
        <property name="username" value="scott" />
        <property name="password" value="tiger" />
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="Mapper.xml"/>
  </mappers>
</configuration>

가장 윗부분은 XML 문서의 유효성체크를 위해 필요한 부분입니다. environment 태그는 트랜잭션 제어를 위한 TransactionManager와 데이터베이스 Connection 인스턴스를 가져오기 위한 DataSource를 포함합니다. dataSource 태그 안에 property 태그를 이용하여 연동하려는 DBMS와 계정 정보를 지정합니다. mappers 태그에는 SQL 코드와 매핑 정의를 가지는 XML 파일인 Mapper 정보를 지정합니다. 

 

* properties

DB 접속에 필요한 네 가지 정보만을 저장하기 위해 파일을 따로 만들 수도 있습니다. src 폴더 안에 jdbc.properties 라는 이름으로 만들어 보겠습니다. jdbc.properties를 이용해 환경설정을 하려면 Configuration.xml 파일에 해당 파일을 등록하고, key 값을 이용해 정보를 지정해 주어야 합니다.

#key=value
oracle.jdbc=oracle.jdbc.driver.OracleDriver
oracle.url=jdbc:oracle:thin:@localhost:1521:xe
oracle.userid=scott
oracle.passwd=tiger

 

* typeAliases

XML 설정에서 타입을 지정할 때 패키지 경로를 함께 지정해 주어야 하는데, 타입 별칭을 부여하면 패키지 경로 없이 별칭만 사용하면 되므로 코드가 깔끔해 집니다. 

 

properties 설정과 typeAliases 설정을 추가한 Configuration.xml 파일은 다음과 같습니다.

<?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>
<!-- jdbc.properties 파일 등록 -->
<properties resource="jdbc.properties"/>
<!-- typealias 등록 -->
<typeAliases>
   <typeAlias type="com.dto.Dept" alias="Dept"/> <!-- Alias 추가 -->
</typeAliases>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <!-- key 값 사용 -->
        <property name="driver" value="${oracle.jdbc}" />
        <property name="url" value="${oracle.url}" />
        <property name="username" value="${oracle.userid}" />
        <property name="password" value="${oracle.passwd}" />
      </dataSource>
    </environment>
  </environments>
  <mappers>
     <mapper resource="Mapper.xml"/>
  </mappers>
</configuration>

 

 

(2) Mapper.xml

 

각각 id를 부여하여 SQL문을 작성해 놓는 파일입니다. MyBatis는 Mapper.xml의 설정에 따라 DB에서 데이터를 가져와 결과를 자동으로 매핑해 줍니다. 기본 구조는 다음과 같습니다. namespace는 Mapper의 이름으로서, 임의로 지정할 수 있으며 Mapper 파일이 여러개인 경우 다른 Mapper와 구분 지어 줍니다. 

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

</mapper>

 

 

 

3. SqlSessionFactory 에서 SqlSession 만들기

 

SqlSession은 DB에 SQL문을 실행하기 위해 필요한 모든 메소드를 가지고 있습니다. SqlSession은 JDBC에서 개발자가 직접 Connection을 생성하고 PreparedStatement를 이용해서 SQL을 실행하던 모든 작업을 내부적으로 자동으로 처리해 줍니다. SqlSession 인스턴스를 만들기 위해서는 SqlSessionFactory가 필요합니다. 저는 SqlSessionFactory를 빌드하고 SqlSession을 생성하기 위한 클래스로 MySqlSessionFactory 클래스를 com.config 패키지 안에 만들었습니다. static 키워드를 지정함으로써 프로그램 실행시 SqlSessionFactory 준비가 완료되도록 하고, 다른 클래스에서 객체 생성 없이 getSqlSession() 메소드를 호출하여 SqlSession 인스턴스를 반환받을 수 있도록 합니다.

package com.config;

import java.io.IOException;
import java.io.InputStream;

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 MySqlSessionFactory {
	static SqlSessionFactory sqlSessionFactory;
	static { //클래스 로딩시 초기화
		String resource = "Configuration.xml"; //설정파일의 이름과 경로 지정
		InputStream inputStream = null;
		try {
			inputStream = Resources.getResourceAsStream(resource); //설정파일 읽어오기
			System.out.println("Configuration.xml 로딩 성공");
		} catch (IOException e) {
			e.printStackTrace();
		}
		sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //SqlSessionFactoryBuilder 생성 후, 읽어온 설정파일로 SqlSessionFactory 빌드
	}
	public static SqlSession getSqlSession() { //SqlSession 반환 
		SqlSession session = sqlSessionFactory.openSession(); //SqlSessionFactory에서 SqlSession 생성
		return session;
	}
}

 

이렇게 하면 MyBatis를 사용하기 위한 기본적인 환경설정이 완료된 것입니다. 이제 필요한 클래스들을 만들고 SQL문을 실행하기 위한 메소드와 Mapper 파일 설정을 하면 됩니다. 

 

 

 

 

▶ 실습

 

1. SELECT

 

저는 scott/tiger 계정의 dept 테이블을 이용해 실습해 보도록 하겠습니다. dept 테이블의 모든 정보를 SELECT하는 프로그램부터 알아보겠습니다. 진행과정은 다음과 같습니다.

 

  1. 프로그램 실행시 Configuration.xml 설정파일을 읽어와 설정파일에 따라 SqlSessionFactory를 빌드합니다. 
  2. Main에서 Service 객체를 생성하면, Service 생성자는 DAO 객체를 생성합니다.
  3. Main에서 Service 클래스의 selectAll() 메소드를 호출합니다.
  4. 호출된 Service 클래스의 selectAll() 메소드는 getSqlSession() 메소드를 호출하여 SqlSession 인스턴스를 반환받고, DAO 클래스의 selectAll() 메소드로 전달합니다. 
  5. DAO 클래스의 selectAll() 메소드는 전달받은 SqlSession 객체를 이용해 SQL문을 실행할 메소드를 호출하며 Mapper 파일에 등록된 id를 지정하고, SQL문 실행 결과를 반환받습니다. 
  6. 반환받은 결과값을 Service 클래스로 리턴하고, Service 클래스에서는 다시 Main으로 리턴합니다. 
  7. Main에서 결과값을 받아 사용할 수 있게 됩니다.

 

(1) DTO

 

DB에서 Dept 레코드를 하나씩 꺼내 저장할 수 있도록 Dept 모델 클래스를 만들어 줍니다. 한 레코드가 가지는 각 컬럼의 정보를 담을 수 있도록 컬럼명, 컬럼타입과 동일한 이름, 타입의 인스턴스 변수를 선언합니다. 저는 확인을 위해 출력문도 추가해 주었습니다.

package com.dto;

public class Dept {
	int deptno;
	String dname;
	String loc;
	public Dept() {
		super();
		System.out.println("---- Dept 기본생성자 ----");
	}
	public Dept(int deptno, String dname, String loc) {
		super();
		this.deptno = deptno;
		this.dname = dname;
		this.loc = loc;
	}
	public int getDeptno() {
		System.out.println("getDeptno() 호출");
		return deptno;
	}
	public void setDeptno(int deptno) {
		System.out.println("setDeptno() 호출");
		this.deptno = deptno;
	}
	public String getDname() {
		System.out.println("getDname() 호출");
		return dname;
	}
	public void setDname(String dname) {
		System.out.println("setDname() 호출");
		this.dname = dname;
	}
	public String getLoc() {
		System.out.println("getLoc() 호출");
		return loc;
	}
	public void setLoc(String loc) {
		System.out.println("setLoc() 호출");
		this.loc = loc;
	}
	@Override
	public String toString() {
		return "Dept [deptno=" + deptno + ", dname=" + dname + ", loc=" + loc + "]";
	}	
}

 

 

(2) Main

 

Main에서 Service 객체를 생성하고 Service 클래스의 selectAll() 메소드를 호출하여 반환받은 결과를 List<Dept> 타입으로 저장하고 있습니다. 이후 받아온 데이터를 순회하며 부서 정보를 모두 출력하고 있습니다.

import java.util.List;

import com.dto.Dept;
import com.service.OracleMyBatisService;

public class OralceMyBatisMain {
	public static void main(String[] args) {
		OracleMyBatisService service = new OracleMyBatisService();
		List<Dept> list = service.selectAll();
		for (Dept dept : list) {
			System.out.println(dept);
		}
	}
}

 

 

(3) Service

 

Service 클래스에서는 getSqlSession() 메소드를 호출해 SqlSession 인스턴스를 받아옵니다. 받아온 SqlSession을 DAO 클래스의 selectAll 메소드를 호출하며 전달합니다. 이후 반환받은 결과를 list에 담고 session을 닫은 후 list를 Main으로 리턴하고 있습니다.

package com.service;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.config.MySqlSessionFactory;
import com.dao.OracleMyBatisDAO;
import com.dto.Dept;

public class OracleMyBatisService {
	OracleMyBatisDAO dao;
	public OracleMyBatisService() {
		super();
		dao = new OracleMyBatisDAO();
	}
	public List<Dept> selectAll() {
		List<Dept> list = null;
		SqlSession session = MySqlSessionFactory.getSqlSession();
		try {
			list = dao.selectAll(session);
		} finally {
			session.close();
		}
		return list;
	}
}

 

 

(4) DAO

 

DAO 클래스의 selectAll 메소드는 전달받은 SqlSession 객체를 이용해 SQL문을 실행하기 위한 메소드를 호출합니다. 이때 SqlSession으로 호출할 수 있는 함수는 selectOne(), selectList(), insert(), update(), delete() 등이 있습니다. 여기서는 모든 부서 정보를 조회하려고 하므로 selectList 메소드를 사용합니다. selectList 메소드는 select한 결과가 여러개일 때 사용하는 메소드로서, select한 결과를 지정한 resultType에 맞게 레코드 하나씩 저장하고 저장한 데이터들을 다시 List에 담아서 반환합니다. 메소드 호출시 Mapper 파일에 등록할 id를 지정합니다. 

package com.dao;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.dto.Dept;

public class OracleMyBatisDAO {
	public List<Dept> selectAll(SqlSession session) {
		List<Dept> list = session.selectList("selectAll");
		return list;
	}
}

 

 

(5) Mapper.xml

 

MyBatis는 Mapper.xml 설정에 따라 SQL문을 실행하고 실행한 결과를 자동으로 매핑하여 반환해 줍니다. selectAll이라는 id의 SQL문을 작성합니다. select한 결과를 레코드 하나씩 Dept 객체에 담도록 resultType을 Dept로 지정합니다. 앞서 Configuration.xml 파일에 타입 별칭을 부여하였으므로 Dept라고만 지정해도 됩니다. 만일 별칭을 부여하지 않은 경우 해당 클래스가 속한 패키지 경로를 추가하여 com.dto.Dept 와 같이 작성해야 합니다. 각 레코드가 Dept 객체로 저장된 후 다시 모든 데이터가 List에 담겨 반환됩니다. 

<?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="Mapper">
   <select id="selectAll" resultType="Dept">
    select * from dept
   </select>
</mapper>

 

최종적으로 Main에서 List를 받아 모든 데이터를 출력하면 다음과 같은 결과를 얻을 수 있습니다. 

 

 

확인을 위해 추가한 출력문들을 보면 MyBatis가 어떤 과정으로 selectList() 메소드를 통해 SQL문을 실행하는지 알 수 있습니다. resultType으로 지정한 Dept로 각 레코드를 담기 위해 Dept의 기본생성자를 호출하며 객체 생성을 합니다. 이후 Dept 클래스의 setXXX() 메소드를 이용해 DB에서 꺼내온 각 레코드의 각 컬럼에 대한 데이터를 설정합니다. 이렇게 모든 레코드를 각각 Dept 객체로 저장하는 작업을 완료한 후, 모든 Dept 객체를 List에 담아 반환하는 것입니다. 

 

 

 

2. INSERT

 

이번에는 부서 정보를 하나 추가해 보겠습니다.

 

(2) Main

 

Main에서 99번 부서를 생성하여 Service 클래스의 insertDept 메소드로 전달합니다.

service.insertDept(new Dept(99, "개발", "서울"));

 

 

(3) Service

 

Service 클래스에서는 SqlSession 인스턴스를 받아온 후, DAO 클래스의 insertDept 메소드를 호출하며 SqlSession과 Dept를 함께 전달합니다. 이때 주의할 점은 SqlSession의 경우 auto commit이 비활성화되어 있기 때문에 반드시 DML 실행 후 commit()을 명시적으로 실행해야 한다는 것입니다. 

public void insertDept(Dept dept) {
	SqlSession session = MySqlSessionFactory.getSqlSession();
	try {
		dao.insertDept(session, dept);
		session.commit();
	} finally {
		session.close();
	}
}

 

 

(4) DAO

DAO 클래스에서는 SqlSession의 insert 메소드를 호출하며 id 정보와 Dept 객체를 함께 전달합니다. 변경된 레코드 개수를 정수값으로 리턴받아 출력하고 있습니다. 

public void insertDept(SqlSession session, Dept dept) {
	int result = session.insert("insertDept", dept);
	System.out.println(result+"개의 레코드 추가");
}

 

 

(5) Mapper.xml

 

insertDept를 id로 갖는 insert SQL문을 작성합니다. Dept 객체를 인자로 받고 있으므로 parameterType을 Dept로 설정해 줍니다. #{ } 는 파라미터 표기법입니다. 이 표기법은 MyBatis에게 PreparedStatement 파라미터를 만들도록 지시합니다. PreparedStatement 이용시 물음표(?) 자리에 setXXX() 메소드로 값을 설정하던 작업이 자동으로 이루어질 수 있도록 하는 것입니다. 인자로 전달받은 Dept 객체에서 deptno, dname, loc 데이터를 꺼내오고 이 데이터가 PreparedStatement 파라미터로 전달되어 SQL문이 실행됩니다. 

<insert id="insertDept" parameterType="Dept">
  insert into dept (deptno, dname, loc) 
  values (#{deptno}, #{dname}, #{loc})
</insert>

 

이에 따른 출력 결과는 다음과 같습니다.

 

 

Main에서 생성한 Dept 객체를 인자로 받아서 Dept 객체의 deptno, dname, loc 데이터를 꺼내오기 위해 getXXX() 함수를 호출한 것을 확인할 수 있습니다. 

 

 

 

3. UPDATE

 

이번에는 99번 부서를 수정해 보겠습니다. UPDATE를 실행하기 위한 과정은 INSERT와 매우 유사합니다.

 

(2) Main

 

Main에서 수정하고 싶은 내용을 반영한 Dept 객체를 생성 후 Service 클래스의 updateDept 메소드로 전달합니다.

service.updateDept(new Dept(99, "영업", "강남"));

 

 

(3) Service 

 

Service 클래스에서는 SqlSession 인스턴스를 받아온 후, DAO 클래스의 updateDept 메소드를 호출하며 SqlSession과 Dept를 함께 전달합니다. 마찬가지로 commit을 실행해야 변경 사항이 반영됩니다.

public void updateDept(Dept dept) {
	SqlSession session = MySqlSessionFactory.getSqlSession();
	try {
		dao.updateDept(session, dept);
		session.commit();
	} finally {
		session.close();
	}
}

 

 

(4) DAO

 

DAO 클래스에서는 SqlSession의 update 메소드를 호출하며 id 정보와 Dept 객체를 함께 전달합니다. 변경된 레코드 개수를 정수값으로 리턴받아 출력하고 있습니다. 

public void updateDept(SqlSession session, Dept dept) {
	int result = session.update("updateDept", dept);
	System.out.println(result+"개의 레코드 업데이트");
}

 

 

(5) Mapper.xml

 

updateDept를 id로 갖는 update SQL문을 작성합니다. Dept 객체를 인자로 받고 있으므로 parameterType을 Dept로 설정해 줍니다. 

<update id="updateDept" parameterType="Dept">
  update dept 
  set dname=#{dname}, loc=#{loc} where deptno=#{deptno}
</update>

 

출력 결과는 다음과 같습니다.

 

 

INSERT와 마찬가지로 표기한 자리에 값을 설정하기 위해 인자로 받은 Dept 객체에서 getXXX() 메소드를 이용해 데이터를 꺼내오고 있는 것을 확인할 수 있습니다. 

 

 

 

4. DELETE

 

이번에는 99번 부서를 삭제해 보겠습니다. 

 

(2) Main

 

Main에서 Service 클래스의 deleteDept 메소드를 호출하며 삭제할 부서의 부서번호를 전달합니다.

service.deleteDept(99);

 

 

(3) Service

 

Service 클래스에서는 SqlSession 인스턴스를 받아온 후, DAO 클래스의 deleteDept 메소드를 호출하며 SqlSession과 int 형의 deptno를 함께 전달합니다. 마찬가지로 commit을 실행해야 변경 사항이 반영됩니다.

public void deleteDept(int deptno) {
	SqlSession session = MySqlSessionFactory.getSqlSession();
	try {
		dao.deleteDept(session, deptno);
		session.commit();
	} finally {
		session.close();
	}
}

 

 

(4) DAO

 

DAO 클래스에서는 SqlSession의 delete 메소드를 호출하며 id 정보와 int 형의 deptno를 함께 전달합니다. 변경된 레코드 개수를 정수값으로 리턴받아 출력하고 있습니다. 

public void deleteDept(SqlSession session, int deptno) {
	int result = session.delete("deleteDept", deptno);
	System.out.println(result+"개의 레코드 삭제");
}

 

 

(5) Mapper.xml

 

deleteDept를 id로 갖는 delete SQL문을 작성합니다. int 형의 deptno를 인자로 받고 있으므로 parameterType을 int로 설정해 줍니다.

<delete id="deleteDept" parameterType="int">
  delete from dept where deptno=#{deptno}
</delete>

 

레코드가 삭제된 것을 확인할 수 있습니다.

 

 

 

 

5. selectOne

 

앞서 selectList 메소드를 사용해 여러개의 레코드를 조회하는 것을 살펴보았습니다. 이번에는 SELECT한 결과가 레코드 한 개인 경우를 알아보겠습니다.

 

(2) Main

 

10번 부서 정보를 조회하기 위해 Service 클래스의 selectByDeptno 메소드로 10을 전달합니다. 이후 리턴받은 결과를 Dept 객체로 저장하여 출력하고 있습니다.

Dept dept = service.selectByDeptno(10);
System.out.println(dept);

 

 

(3) Service 

 

Service 클래스에서는 SqlSession 인스턴스를 받아온 후, DAO 클래스의 selectByDeptno 메소드를 호출하며 SqlSession과 int 형의 deptno를 함께 전달합니다. 

public Dept selectByDeptno(int deptno) {
	Dept dept = null;
	SqlSession session = MySqlSessionFactory.getSqlSession();
	try {
		dept = dao.selectByDeptno(session, deptno);
	} finally {
		session.close();
	}
	return dept;
}

 

 

(4) DAO

 

DAO 클래스에서는 SqlSession의 selectOne 메소드를 호출하며 id 정보와 int 형의 deptno를 함께 전달합니다. 결과를 Dept 객체로 반환받아 저장하고 있습니다. 

public Dept selectByDeptno(SqlSession session, int deptno) {
	Dept dept = session.selectOne("selectByDeptno", deptno);
	return dept;
}

 

 

(5) Mapper.xml

 

selectByDeptno를 id로 갖는 select SQL문을 작성합니다. int 형의 deptno를 인자로 받고 있으므로 parameterType은 int로 설정하고, SELECT한 결과를 Dept 객체로 저장해 리턴해야 하므로 resultType은 Dept로 설정합니다.

<select id="selectByDeptno" parameterType="int" resultType="Dept">
  select * from dept where deptno=#{deptno}
</select>

 

다음과 같이 10번 부서 정보가 출력됩니다.

 

 

 

이상으로 MyBatis를 시작하기 위한 환경설정과 기본적인 활용 방법에 대해 알아보았습니다.

 

 

 

 

▶ References

 

 

 

'JAVA' 카테고리의 다른 글

[JAVA] MyBatis - 동적 SQL  (0) 2022.06.19
[JAVA] MyBatis - HashMap 사용  (0) 2022.06.16
[JAVA] JDBC - DAO, DTO 패턴  (0) 2022.06.09
[JAVA] JDBC - PreparedStatement  (0) 2022.06.07
[JAVA] JDBC 기본 개념과 프로그래밍 단계  (0) 2022.06.06

댓글