[MyBatis] 01. 소개 및 환경 설정
- -
앞으로 우리가 사용할 MyBatis에 대해 간략히 알아보자.
MyBatis
소개
MyBatis란 SQL을 편하게 작성할 수 있도록 SQL-Object 매핑을 지원하는 Persistence Framework으로 주요 특징은 다음과 같다.
- 기본적으로 PreparedStatement를 사용하기 때문에 SQL 삽입 공격에 대해 안전하다.
- ResultSet의 내용을 DTO나 컬렉션에 저장하기 위한 코드가 필요 없다.
- 일반적으로 XML에서 SQL 쿼리를 작성한다.
- 프로그램 코드와 SQL의 분리로 코드가 간결해지고 유지 보수성이 향상된다.
MyBatis에 대해서는 아래 사이트에서 한글로 자세한 document를 제공하므로 즐겨 찾기에 추가하고 자주 살펴보기를 권한다.
기본 구조
MyBatis는 다음의 구조를 갖는다.
- mybatis-config.xml
- MyBatis 동작에 대한 설정을 담는 파일로 최근에는 Java 기반으로 작성한다.
- Spring Boot과 연동되면서 application.properties에서도 동일한 내용을 설정할 수 있다.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="org/mybatis/example/config.properties"> <!--속성정보로딩-->
<property name="username" value="dev_user"/> <!--속성정보재정의-->
<property name="password" value="F2Fa3!33TYyg"/>
</properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/> <!--TX관리를 직접 처리-->
<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"/> <!--mapper 등록-->
</mappers>
</configuration>
- mapper.xml
- xml로 SQL 쿼리를 정의해서 등록하며 파라미터 및 결과에 대한 매핑을 처리한다.
- 일반적으로 테이블당 하나의 mapper.xml을 작성한다.
- Java 파일로 작성 가능하나 동적 쿼리에서는 xml이 편하므로 xml로 작성한다.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.mybatis.example.BlogMapper">
<select id="selectBlog" resultType="Blog">
select * from Blog where id = #{id}
</select>
</mapper>
파일에 대한 템플릿은 https://mybatis.org/mybatis-3/ko/getting-started.html에서 확인할 수 있다.
mybatis-config에서는 여러 mapper 들에 정의된 sql들을 로딩해서 SQL map이라는 것을 구성하는데 이를 mapped statement라고 한다. 이 문장을 호출할 때 파라미터로 JavaBeans, java.util.Map, primitive, String 가 전달될 수 있고 호출의 결과로도 동일한 타입을 받을 수 있다.
실습 환경 준비 - legacy spring
의존성 구성
Spring에서 MyBatis를 사용하기 위해 필요한 의존성은 다음과 같다.
- org.mybatis.mybatis: mybatis
- com.mysql.mysql-connector-j: mysql
- com.zaxxer.HikariCP: connection pool
- org.mybatis.mybatis-spring: spring과 mybatis 연동
- org.springframework.spring-jdbc: transaction 처리에 필요
database 접근 정보 작성
JDBC를 사용하려면 언제나 driver-class-name/url/username/password에 대한 정보가 필요하다. 이 정보들을 소스코드에 하드코딩할 수도 있지만 특히 password는 수시로 변동될 수 있기 때문에 소스와 별도로 관리하는 것이 좋다. 이를 위해 src/main/resources/db/dbinfo.properties를 작성하자.
datasource.driver-class-name=com.mysql.cj.jdbc.Driver
datasource.url=jdbc:mysql://localhost:3306/world?serverTimezone=UTC
datasource.password=quietjun
datasource.username=quietjun
이런 properties 파일을 읽어들일 때는 @PropertySource를 사용하며 읽어들인 속성을 사용할 때는 @Value를 사용한다.
@Configuration
@ComponentScan("com.doding")
@PropertySource("classpath:/db/dbinfo.properties")
public class ApplicationConfig {
@Value("${datasource.driver-class-name}")
private String driver;
}
필요한 빈 구성
MyBatis를 스프링에서 사용하기 위해서는 최소한 4개의 빈이 필요하다.
- DataSource: Database에 접속하기 위한 객체로 일반적으로 HikariDataSource등 구현체를 사용한다.
- PlatformTransactionManager: @Transactional을 통해 선언적 트랜젝션을 처리하기 위해 사용된다.
- SqlSessionFactoryBean: SqlSessionTemplate을 만들기 위한 빈으로 datasource, typealias, mapper 위치를 설정한다.
- SqlSessionTemplate: 실제 쿼리를 실행하기 위한 빈으로 SqlSessionFactoryBean을 이용해서 구성한다.
@Configuration
@PropertySource("classpath:/db/dbinfo.properties")
@ComponentScan("com.doding")
@EnableTransactionManagement // @Transactional 사용을 위함
public class ApplicationConfig {
@Bean
public DataSource ds(@Value("${datasource.driver-class-name}") String driver,
@Value("${datasource.url}") String url,
@Value("${datasource.password}") String pass,
@Value("${datasource.username}") String username) {
HikariDataSource ds = new HikariDataSource();
ds.setDriverClassName(driver);
ds.setJdbcUrl(url);
ds.setUsername(username);
ds.setPassword(pass);
return ds;
}
@Bean
public PlatformTransactionManager transactionManager(DataSource ds) {
return new DataSourceTransactionManager(ds);
}
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource ds) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(ds);
// DTO의 위치를 설정한다.
factoryBean.setTypeAliasesPackage("com.doding.mybatis.model.dto");
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
// mapper xml 파일의 위치를 설정한다.
factoryBean.setMapperLocations(resolver.getResources("classpath:/db/mapper/*.xml"));
return factoryBean;
}
@Bean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactoryBean sfb) throws Exception {
SqlSessionTemplate template = new SqlSessionTemplate(sfb.getObject());
return template;
}
}
실습 환경 준비 - spring boot
의존성 구성
SpringBoot에서 MyBatis를 사용하기 위해 필요한 의존성은 다음과 같다.
- com.mysql.mysql-connector-j: mysql
- mybatis-spring-boot-starter: mybatis와 spring 연결 모듈은 물론 HikariCP, spring-jdbc를 포함한다.
application.properties
SpringBoot에서는 MyBatis를 사용하겠다는 선언만으로 MybatisAutoConfiguration이 동작하고 DataSource 생성에 대한 환경이 필요하다. 이에 대한 설정은 application.properties에 작성해준다.
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/world?serverTimezone=UTC
spring.datasource.password=quietjun
spring.datasource.username=quietjun
DataSource이외에 필요한 빈(PlatformTransactionManager, SqlSessionTemplate) 도 대부분 자동 구성된다. 단지 필요한 설정들만 해주면 된다.
# DTO가 있는 곳을 지정해서 mapper에서 fully qualified name을 사용하지 않고 클래스만 사용 가능
mybatis.type-aliases-package=com.doding.mybatis.model.dto
# 깊이에 상관 없이 /mappers의 모든 하위 경로에 있는 모든 xml 문서를 사용한다.
mybatis.mapper-locations=classpath:/db/mapper/*.xml
# 또는 전통적인 mybatis-config.xml 파일이 있다면 위치를 지정할 수도 있다.
#mybatis.config-location=classpath:/mybatis-config.xml
설정 확인
빈 설정 확인
테스트를 통해 이제까지 구성한 빈(DataSource, SqlSessionTemplate)이 정상적으로 동작하는지 확인해보자.
public class MyBatisConfigTest {
@Autowired
DataSource ds;
@Autowired
SqlSessionTemplate sessionTemplate;
@Test
public void baseBeanTest() {
Assertions.assertNotNull(ds);
Assertions.assertNotNull(sessionTemplate);
Assertions.assertEquals(ds.getClass().getSimpleName(), "HikariDataSource");
Assertions.assertNotNull(sessionTemplate.getConnection());
}
}
'MyBatis' 카테고리의 다른 글
[MyBatis] 05. 기타 (0) | 2023.06.18 |
---|---|
[MyBatis] 04. 동적 쿼리 (0) | 2023.06.18 |
[MyBatis] 03. 조회 결과의 매핑 (0) | 2023.06.18 |
[MyBatis] 02. CRUD (0) | 2023.06.18 |
Spring + mybatis + PageHelper (4) | 2020.06.23 |
소중한 공감 감사합니다