JDBC
(Java Database Connectivity)
JDBC(Java Database Connectivity)는 자바에서 가장 오래된 데이터베이스 연동 기술로서,
모든 관계형 데이터베이스에 대해서 동일한 자바 코드를 사용합니다.
JDBC는 다형성(Poloymorphism)을 기반으로 동작하기 때문에
데이터베이스와 무관하게 동일한 자바 코드를 사용할 수 있습니다.
DAO(Data Access Object)
DAO(Data Access Object) 클래스를 구현할 때는 JDBC(java.sql 패키지)가 제공하는 인터페이스를 이용합니다.
그러면 인터페이스를 구현한 드라이버가 실질적인 데이터베이스 연동을 처리합니다.
따라서 데이터베이스가 변경되는 경우에 각 벤더에서 제공하는 드라이버만 교체해 주면 됩니다.
public class EmployeeDAO {
private Connection conn = null;
private PreparedStatement stmt = null;
private ResultSet rs = null;
private String INSERT_EMP = "insert into s_emp(id, name, start_date, title, dept_name, salary) " +
"values((select nvl(max(id), 0) + 1 from s_emp), ?, ?, ?, ?, ?)";
private String LIST_EMP =
"select id, name, start_date, title, dept_name, salary " +
"from s_emp order by name";
public void insertEmployee(EmployeeVO vo) {
System.out.println("===> JDBC 기반으로 직원 등록 기능 처리");
try {
conn = getConnection();
stmt = conn.prepareStatement(INSERT_EMP);
stmt.setString(1, vo.getName());
stmt.setTimestamp(2, vo.getStartDate());
stmt.setString(3, vo.getTitle());
stmt.setString(4, vo.getDeptName());
stmt.setDouble(5, vo.getSalary());
stmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
close(stmt, conn);
}
}
(...)
public Connection getConnection() {
try {
Class.forName("org.h2.Driver");
String url = "jdbc:h2:tcp://localhost/~/test";
conn = DriverManager.getConnection(url, "sa", "");
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
public void close(ResultSet rs, Statement stmt, Connection conn) {
try {
if (rs != null) {
rs.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
rs = null;
}
try {
if (stmt != null) stmt.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
stmt = null;
}
try {
if (conn != null && !conn.isClosed()) conn.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
conn = null;
}
}
public void close(Statement stmt, Connection conn) {
try {
if (stmt != null) {
stmt.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
stmt = null;
}
try {
if (conn != null && !conn.isClosed()) conn.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
conn = null;
}
}
JDBC의 문제
커넥션을 연결하고 종료하는 중복되는 코드를 별도의 메소드(getConnection, close)로 분리시켰음에도 불구하고 여전히 모든 데이터베이스 연동 메서드(insertEmployee, getEmployeeList)에 "반복되는 코드"가 등장합니다.
또한, SQL 구문들이 DAO 클래스에 포함되어 있기 때문에, SQL 명령어를 수정하기 위해서는 SQL이 선언된 DAO 클래스를 찾아야 합니다. 수정한 이후에는 다시 컴파일을 해야 합니다. 이런 JDBC의 문제를 해결하기 위해 마이바티스와 같은 "SQL 매퍼 프레임워크"가 등장하였습니다.
My Batis(SQL Mapper)
마이바티스(MyBatis) 프레임워크는 아파치에서 만든 아이바티스(iBATIS) 프레임워크에서
파생된 SQL 매퍼 프레임워크입니다.
마이바티스는 JDBC로 데이터베이스를 연동하기 위해 드라이버 로딩, 커넥션 연결, 해제까지 복잡하고
반복적인 작업을 프레임워크가 대신 처리해 주기 때문에 개발자는 비즈니스 로직에 집중할 수 있게 됩니다.
마이바티스는 자바 코드와 SQL을 분리합니다.
SQL 매퍼라는 XML파일을 만들어서 DAO 클래스에서 사용할 SQL을 저장하고 관리합니다.
➜ SQL 명령어를 자바 코드와 분리하여 한 곳에 모아서 관리하기 때문에
SQL을 검색하기도 쉽고, SQL을 수정했을 때 자바 소스를 다시 컴파일하지 않아도 됩니다.
마이바티스에서는 XML파일에 분리된 SQL을 실행하기 위한 자바코드는
한 줄에 불과하기 때문에 데이터베이스 연동이 매우 간결해졌습니다.
DAO
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
public class EmployeeDAO {
private SqlSession mybatis;
public EmployeeDAO() {
try {
Reader reader = Resources.getResourceAsReader("org/example/chapter01/mybatis/sql-map-config.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
mybatis = sessionFactory.openSession();
} catch (IOException e) {
e.printStackTrace();
}
}
public void insertEmployee(EmployeeVO vo) {
System.out.println("==> MyBatis 기반으로 회원 등록 기능 처리");
mybatis.insert("EmployeeDAO.insertEmployee", vo);
mybatis.commit();
}
public List<EmployeeVO> getEmployeeList() {
System.out.println("==> MyBatis 기반으로 회원 목록 조회 기능 처리");
return mybatis.selectList("EmployeeDAO.getEmployeeList");
}
}
mapping.xml
<?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="EmployeeDAO">
<!-- ResultMap 선언 -->
<resultMap type="employee" id="employeeResult">
<result property="id" column="ID"/>
<result property="name" column="NAME"/>
<result property="startDate" column="START_DATE"/>
<result property="title" column="TITLE"/>
<result property="deptName" column="DEPT_NAME"/>
<result property="salary" column="SALARY"/>
</resultMap>
<!-- 직원 등록 SQL -->
<insert id="insertEmployee" parameterType="employee">
insert into s_emp(id, name, start_date, title, dept_name, salary)
values((select nvl(max(id), 0) + 1 from s_emp),
#{name},
#{startDate},
#{title},
#{deptName},
#{salary})
</insert>
<!-- 직원 목록 검색 SQL -->
<select id="getEmployeeList" resultMap="employeeResult">
select id, name, start_date, title, dept_name, salary
from s_emp
order by name
</select>
</mapper>
config.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>
<!-- 매퍼 XML에서 사용할 Alias 선언 -->
<typeAliases>
<typeAlias alias="employee" type="org.example.chapter01.mybatis.EmployeeVO" />
</typeAliases>
<!-- 데이터소스 설정 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:tcp://localhost/~/test"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</dataSource>
</environment>
</environments>
<!-- 매퍼 XML 등록 -->
<mappers>
<mapper resource="org/example/chapter01/mybatis/s_emp-mapping.xml"/>
</mappers>
</configuration>
MaBatis의 문제
MyBatis에서 직접 SQL-Mapper를 작성할 때 발생하는 오류를 정확하게 잡기 어려워서
오타와 같은 부분에 대하여 많은 어려움이 있었습니다. MyBatis와 같은 Data-Mapper는 자바코드와 SQL을
분리시켜 편리성을 JDBC에 비해 향상시켰습니다.
그리고 프레임워크에서 데이터베이스연동에 필요한 자바 코드를 제공함으로써
개발자가 작성해야 했던 수많은 코드를 제거할 수 있었습니다.
하지만 이런 장점들에도 불구하고 여전히 개발자가 직접 SQL을 관리하기 때문에 데이터
구조가 변경되는 상황에서는 효율적으로 대처하기가 어렵습니다.
참고 서적 : JPA 퀵스타트
'데이터베이스 탐구' 카테고리의 다른 글
데이터베이스) RDB와 NoSQL (2) | 2023.07.31 |
---|---|
데이터베이스) 트랜잭션 (0) | 2023.07.26 |
SQL) DROP, TRUNCATE, ALTER (0) | 2023.05.01 |
MySQL) 인텔리제이에서 테이블 만들어보기 (0) | 2023.05.01 |
프로그래머스) (mySQL) 가장 비싼 상품 구하기 (0) | 2023.04.30 |