Spring4 & MyBatis
[부스트코스] 웹 프로그래밍 기반의 설정에서 추가 설정으로 확장하기 위한 포스팅
목표
- spring4 pom.xml 설정
- mybatis dependency 추가
- mybatis java config
- domain, mapper, sql 샘플 작성
- mapper 테스트
Spring4의 Java Config 향상 기능을 통해 Mybatis를 구성하는 xml 제외하기
mybatis-spring 라이브러리에서 제공하는 @MapperScan 어노테이션을 사용하여 MyBatis Domain Mapper에 대해 패키지단위로 검색이 가능하다.
Servlet 3+와 결합하는 경우 XML없이 응용 프로그램을 구성하고 실행할 수 있다.
프로젝트 스펙 및 설정 구조
모듈 | 버전 | 설명 |
---|---|---|
Spring Framework | 4.3.15.RELEASE | |
MyBatis | 3.5.2 | |
mybatis-spring | 2.0.2 |
- src/main
- java/com/seok/mybatis/
config/
* AppConfig.java
* DBConfig.java
* MybatisConfig.java
domain/
* Product.java
persistence/
* ProductMapper.java
- resources/mapper/
* ProductMapper.xml
* pom.xml
설정
-
MyBatis 사용을 위한 mybatis, mybatis-spring dependency를 추가 한다.
물론 DB를 사용하기 위한 프로젝트이기 때문에 spring-jdbc, mysql-connector-java도 추가
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
- AppConfig.java
- 스프링 설정 클래스
- DBConfig와 MyBatisConfig를 분리해서 Import하였다.
- 같은 클래스안에서 설정해도 무관
@Configuration
@Import({DBConfig.class, MybatisConfig.class})
public class AppConfig {
}
- DBConfig.java
- DB 설정관련 클래스
- java 파일 내에 설정 정보를 넣지 않고 properties 파일을 사용하여 보안 및 배포 관리
@Configuration
@EnableTransactionManagement
@PropertySource({ "classpath:db.properties" })
public class DBConfig implements TransactionManagementConfigurer {
@Value("${spring.datasource.driver-class-name}")
private String driverClassName;
@Value("${spring.datasource.url}")
private String url;
@Value("${spring.datasource.username}")
private String userName;
@Value("${spring.datasource.password}")
private String password;
@Override
public PlatformTransactionManager annotationDrivenTransactionManager() {
return transactionManager();
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(userName);
dataSource.setPassword(password);
return dataSource;
}
}
-
- line 2: MyBatis Mapper가 있는 패키지 설정
- line 9: MyBatis.xml 파일에서 resultType으로 사용할 수 있는 도메인 개체를 포함하는 패키지 설정
(SQL쿼리에서 Java 객체를 반환하는 것은 ORM 문제를 해결)
- MyBatis를 설정하기 위해 SqlSessionFactoryBean를 사용
@Configuration
@MapperScan("com.seok.mybatis.persistence")
public class MybatisConfig {
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) throws IOException {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
sessionFactory.setTypeAliasesPackage("com.seok.mybatis.domain");
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
return sessionFactory;
}
}
- Product.java
- Product 도메인 객체는 실제 단순한 POJO
public class Product implements Serializable{
private static final long serialVersionUID = 3690807750019415954L;
private int id;
private int categoryId;
private String desc;
private String content;
private String event;
// constructor, setter, getter
}
- ProductMapper.java
- Mapper 클래스는 해당 mapper.xml에 정의된 sql문과 일치하는 메서드를 정의하는 단순한 인터페이스이다.
- xml로 SQL을 정의하는 대신 어노테이션으로 간단한 SQL문을 작성하는 것이 가능하지만, query가 번거로워져 복잡한 Query는 사용하지 않는다.
import org.apache.ibatis.annotations.Select;
import kr.or.seok.naver.domain.Product;
public interface ProductMapper {
public List<Product> getAllProducts();
// Simple SQL
@Select("SELECT COUNT(*) totalCnt FROM product")
public int getTotalCnt();
}
- ProductMapper.xml
- 필요한 쿼리 및 메서드를 생성 가능
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.seok.mybatis.persistence.ProductMapper">
<cache />
<select id="getAllProducts" resultType="Product">
SELECT
id,
category_id,
description,
content,
event
FROM product
</select>
</mapper>
테스트
- TestMyBatis.java
- Test 코드는 Mockito나 Junit을 사용하는 것이 편리
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class TestMyBatis {
@Autowired
ProductMapper prodMapper;
@Test
public void testMapper() {
// prodMapper.getAllProducts();
}
@Test
public void testTotalProducts() {
// productMapper.getTotalCnt();
}
}
결과
- TotalCnt()
- Product의 전체 row 갯수를 확인하기 위한 메서드로 50개가 조회되고 있음을 알 수 있다.
23:53:03.208 [main] DEBUG com.seok.mybatis.persistence.ProductMapper.getTotalCnt - ==> Preparing: SELECT COUNT(*) totalCnt FROM product
23:53:03.251 [main] DEBUG com.seok.mybatis.persistence.ProductMapper.getTotalCnt - ==> Parameters:
23:53:03.276 [main] DEBUG com.seok.mybatis.persistence.ProductMapper.getTotalCnt - <== Total: 1
23:53:03.282 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3daf7722]
23:53:03.282 [main] DEBUG org.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
23:53:03.336 [main] INFO com.seok.mybatis.config.TestMyBatis - 50
- getAllProducts()
- Product의 모든 row를 조회하기 위한 테스트 메서드로 50개의 Product리스트가 조회되고 있음을 확인할 수 있다.
23:53:03.348 [main] DEBUG com.seok.mybatis.persistence.ProductMapper.getAllProducts - ==> Preparing: SELECT id, category_id, description, content, event FROM product
23:53:03.348 [main] DEBUG com.seok.mybatis.persistence.ProductMapper.getAllProducts - ==> Parameters:
23:53:03.372 [main] DEBUG com.seok.mybatis.persistence.ProductMapper.getAllProducts - <== Total: 50
23:53:03.379 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@52066604]
23:53:03.379 [main] DEBUG org.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
23:53:03.419 [main] INFO com.seok.mybatis.config.TestMyBatis - [ {
"id" : 1,
"categoryId" : 0,
"desc" : null,
"content" : "",
"event" : ""
},
...
}]
'Edu > BoostCourse - Web' 카테고리의 다른 글
[API Document] Spring에 Swagger 적용하기 (0) | 2020.04.14 |
---|---|
[Servlet] Dynamic Web Project 3.x spec (0) | 2020.03.12 |
[Servlet] Dynamic Web Project 2.5 spec (0) | 2020.03.12 |
[Spring] web.xml vs Initializer with Spring (0) | 2020.03.04 |
[BoostCourse] 웹 프론트엔드 취약점 (0) | 2020.03.02 |