🚀 학습 목표
1. MyBatis 란 뭘까?
2. MyBatis 의존성 설정 확인
3. yml 파일 매퍼 설정 확인
4. mapper 패키지 및 xml 파일 생성
📌 MyBatis 설정
# MyBatis 설정
mybatis:
mapper-locations:
- classpath:mapper/**/*.xml # MyBatis 매퍼 파일 경로 설정 (모든 XML 매퍼 파일 포함)
configuration:
map-underscore-to-camel-case: true # 데이터베이스의 언더스코어 네이밍을 카멜 케이스로 자동 매핑
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # MyBatis SQL 로그를 콘솔에 출력
🔹 1. MyBatis란?
MyBatis는 자바 언어를 위한 데이터베이스 연동 프레임워크로, SQL 쿼리와 자바 코드를 매핑하고 관리할 수 있도록 도와줍니다. SQL을 직접 작성하는 대신, XML 파일이나 어노테이션을 사용하여 쿼리를 정의하고, 자바 객체와 데이터베이스 간의 매핑을 설정할 수 있습니다.
📌 순수 JDBC 코드 예시
import java.sql.*;
public class JDBCExample {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/mydatabase";
String username = "root";
String password = "password";
try (Connection connection = DriverManager.getConnection(url, username, password)) {
System.out.println("데이터베이스 연결 성공!");
String sql = "SELECT * FROM users WHERE id = ?";
try (PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setInt(1, 1);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
System.out.println("사용자 ID: " + resultSet.getInt("id"));
System.out.println("사용자 이름: " + resultSet.getString("name"));
} else {
System.out.println("사용자를 찾을 수 없습니다.");
}
}
}
} catch (SQLException e) {
System.out.println("데이터베이스 연결 오류: " + e.getMessage());
}
}
}
🔹 2. MyBatis 주요 개념
✅ 1) 매퍼(Mapper)
- SQL 쿼리와 자바 메서드를 연결하는 인터페이스 또는 XML 파일
- MyBatis가 데이터베이스와 상호작용할 수 있도록 설정
✅ 2) SQL 쿼리 매핑
- MyBatis는 SQL 쿼리를 XML 파일이나 어노테이션으로 정의하고, 이를 통해 코드와 SQL을 분리
✅ 3) 파라미터 매핑
- SQL 쿼리에 필요한 입력 값을 자바 객체의 속성과 매핑하여 활용
✅ 4) 결과 매핑
- SQL 실행 결과를 자바 객체로 변환하여 활용 가능
✅ 5) 세션(Session)
- 데이터베이스와 연결을 관리하는 객체로, 쿼리를 실행할 때마다 세션을 생성하고 관리
📌 3. MyBatis XML 태그 정리
MyBatis의 XML 매퍼에서 사용되는 주요 태그들을 정리해보겠습니다.
🔹 1) <mapper>
- XML 문서가 특정 매퍼 인터페이스와 연결됨을 나타냅니다.
🔹 2) <select>
- SELECT 쿼리를 정의하는 태그
- id 속성: 매퍼 인터페이스의 메서드 이름과 일치해야 함
- resultType: 결과를 매핑할 자바 클래스 지정
<select id="getUser" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
🔹 3) <insert>, <update>, <delete>
- 각각 INSERT, UPDATE, DELETE 쿼리를 정의하는 태그
- parameterType: 전달될 파라미터의 타입을 지정
<insert id="addUser" parameterType="User">
INSERT INTO users (name, email) VALUES (#{name}, #{email})
</insert>
🔹 4) <resultMap>
- SQL 결과를 자바 객체의 필드와 매핑할 때 사용
- 복잡한 조인 쿼리나 상속 관계를 표현하는데 유용
<resultMap id="UserResultMap" type="User">
<id property="id" column="id"/>
<result property="name" column="name"/>
</resultMap>
🔹 5) <sql> & <include>
- 재사용 가능한 SQL 조각을 정의할 때 사용
<sql id="userColumns">
id, name, email, created_at
</sql>
<select id="getUser" resultType="User">
SELECT <include refid="userColumns"/> FROM users WHERE id = #{id}
</select>
🔹 6) <if>, <choose>, <when>, <otherwise>
- SQL 쿼리를 동적으로 생성할 때 사용
<select id="getUsers" resultType="User">
SELECT * FROM users
<where>
<if test="name != null"> AND name = #{name} </if>
<if test="email != null"> AND email = #{email} </if>
</where>
</select>
🔹 7) <foreach>
- 컬렉션을 반복 처리하여 IN 절을 만들 때 유용
<select id="getUsersByIds" resultType="User">
SELECT * FROM users WHERE id IN
<foreach collection="idList" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
동적 SQL 사용 시, 쿼리의 가독성과 유지보수성을 위해 간결하게 유지하는 것이 중요합니다. 복잡한 동적 쿼리는 디버깅과 유지보수를 어렵게 할 수 있으므로, 꼭 필요한 경우에만 사용하는 것이 바람직합니다.
🔹 2. MyBatis 의존성 설정 확인
https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter/3.0.3
📌의존성 추가
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3'
🔹 3. yml 파일 매퍼 설정 확인
#mybatis 설정 부분 입니다.
mybatis:
mapper-locations:
- classpath:mapper/**/*.xml # MyBatis 매퍼 파일 위치를 설정합니다. **는 모든 디렉토리, *.xml은 모든 XML 파일을 의미합니다.
configuration:
map-underscore-to-camel-case: true # 데이터베이스의 언더스코어 네이밍(예: column_name)을 자바의 카멜케이스 네이밍(예: columnName)으로 매핑합니다.
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # SQL 로깅 구현체를 설정합니다. 이 설정을 통해 콘솔에 SQL 로그를 출력합니다.
logging:
level:
org.apache.ibatis: DEBUG # MyBatis 로깅 레벨을 DEBUG로 설정하여, 실행되는 SQL 쿼리와 내부 로깅 정보를 콘솔에 출력합니다.
classpath:mapper/**/*.xml은 mapper 디렉토리와 그 하위의 모든 디렉토리에 있는 XML 파일을 클래스 경로에서 찾겠다는 의미입니다. 즉, MyBatis 매퍼 파일들이 프로젝트의 클래스 경로 아래 mapper 디렉토리에 위치해야 합니다.
🔹 4. mapper 패키지 및 xml 파일 생성
UserRepository + user.xml 정의
인터페이스 설계 - 역할을 설계하고 구현은 (xml 파일에서 처리)
UserRepository.java 파일 생성
package com.tenco.bank.repository.interfaces;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import com.tenco.bank.repository.model.User;
//interface 와 user.xml 매칭 - (메서드 명 기준)
@Mapper // 반드시 선언해주어 한다.
public interface UserRepository {
public int insert(User user);
public int updateById(User user);
public int deleteById(Integer id);
public User findById(Integer id);
public List<User> findAll();
}
src/main/resources/user.xml 파일 생성 (UserRepository 구현체)
<?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="com.tenco.bank.repository.interfaces.UserRepository">
<!-- 반드시 세미콜론을 제거 해야 한다 -->
<!-- #{username} 객체에 속성값으로 설정 해야 한다 -->
<insert id="insert">
insert into user_tb (username, password, fullname, created_at)
values( #{username}, #{password}, #{fullname}, now())
</insert>
<update id="updateById">
update user_tb set username = #{username},
password = #{password},
fullname = #{fullname} where id = #{id}
</update>
<delete id="deleteById">
delete from user_tb where id = #{id}
</delete>
<select id="findById" resultType="com.tenco.bank.repository.model.User">
select * from user_tb where id = #{id}
</select>
<select id="findAll" resultType="com.tenco.bank.repository.model.User">
select * from user_tb
</select>
</mapper>
: 쿼리는 항상 DB 에서 테스트 후에 복사 붙여 넣기 해주세요 (H2에 문법과 RDBMS 에서 적용되는 문법이 다를 수 있습니다.)
📌AccountRepository.java 파일 생성
package com.tenco.bank.repository.interfaces;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import com.tenco.bank.repository.model.Account;
@Mapper // 반드시 작성
public interface AccountRepository {
public int insert(Account account);
public int updateById(Account account);
public int deleteById(Integer id, String name);
// 고민! - 계좌 조회
// --> 한사람에 유저는 여러개의 계좌 번호를 가질 수 있다.
public List<Account> findByUserId(@Param("userId") Integer principalId);
// --> account id 값으로 계좌 정보 조회
public Account findByNumber(@Param("number") String id);
// 코드 추가 예정
}
📌 account.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="com.tenco.bank.repository.interfaces.AccountRepository">
<insert id="insert">
insert into account_tb(number, password, balance, user_id, created_at)
values(#{number}, #{password}, #{balance}, #{userId}, now())
</insert>
<update id="updateById">
update account_tb set number = #{number}, password = #{password},
balance = #{balance}, user_id = #{userId} where id = #{id}
</update>
<delete id="deleteById">
delete from account_tb where id = #{id}
</delete>
<select id="findByUserId" resultType="com.tenco.bank.repository.model.Account">
select * from account_tb where user_id = #{userId}
</select>
<select id="findByNumber" resultType="com.tenco.bank.repository.model.Account">
select * from account_tb where number = #{number}
</select>
</mapper>
📌 HistoryRepository.java 파일 생성
package com.tenco.bank.repository.interfaces;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import com.tenco.bank.repository.model.History;
@Mapper
public interface HistoryRepository {
public int insert(History history);
public int updateById(History history);
public int deleteById(Integer id);
// 계좌 조회
public History findById(Integer id);
public List<History> findAll();
}
📌 history.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="com.tenco.bank.repository.interfaces.HistoryRepository">
<insert id="insert" parameterType="com.tenco.bank.repository.model.History">
insert into
history_tb(
amount, w_balance, d_balance,
w_account_id, d_account_id
)
values(
#{amount}, #{wBalance}, #{dBalance},
#{wAccountId}, #{dAccountId}
)
</insert>
<update id="updateById" parameterType="com.tenco.bank.repository.model.History">
update history_tb
set amount = #{amount},
w_balance = #{wBalance},
d_balace = #{dBalance},
w_account_id = #{wAccountId},
d_account_id = #{dAccountId}
where id =
#{id}
</update>
<delete id="deleteById" parameterType="int">
delete from history_tb
where id = #{id}
</delete>
<select id="findById" resultType="com.tenco.bank.repository.model.History">
select * from history_tb where id = #{id}
</select>
<select id="findAll" resultType="com.tenco.bank.repository.model.History">
select * from history_tb
</select>
</mapper>
마무리 정리
📌 MyBatis는 SQL과 코드의 분리를 통해 유지보수성을 높이고, JDBC보다 효율적으로 데이터베이스를 다룰 수 있습니다.
📌 XML 기반뿐만 아니라 어노테이션 기반으로도 사용할 수 있으며, 동적 SQL을 활용하면 복잡한 조건문도 쉽게 처리할 수 있습니다.
📌 대규모 프로젝트에서는 MyBatis의 매퍼 구조를 잘 설계하여 유지보수를 쉽게 하고, 필요 시 Hibernate 등과 병행 사용을 고려할 수도 있습니다.
📌 Spring Boot와 결합하여 사용할 때는 Configuration 설정과 세션 관리를 신경 써야 합니다.
'Spring' 카테고리의 다른 글
Spring[Spring boot] Bank App - 회원가입(화면구현) (2) | 2025.02.15 |
---|---|
[Spring boot] Bank App - 회원가입 (0) | 2025.02.15 |
[Spring boot] Bank App - Exception Handler (0) | 2025.02.13 |
[Spring boot] Bank App - MainController, mainPage.jsp 구현 (2) | 2025.01.15 |
[Spring boot] Bank App - 화면 구현(레이아웃 분리) (0) | 2025.01.15 |