MyBatis \ SQL 매핑을 위한 퍼시스턴스 프레임워크

Jeonghak Cho·2021년 6월 14일
0

개요

MyBatis는 XML과 애노테이션을 사용하여 데이터베이스 SQL 문과 스토어드 프로시져를 처리하는 자바 퍼시스턴스 프레임워크입니다.

여기서는, My Batis를 이용하여 AWS 의 Aurora PostgreSQL 데이터 베이스에 연결하여 SQL을 사용하여 데이터를 입출력하는 방법을 설명합니다. Spring Boot 를 사용하여 사용자 테이블(users) 내 데이터를 웹브라우저로 데이터를 조회합니다.

아키텍처


JDK 8, Spring Boot 기반으로 mybatis 2.1.0을 사용했습니다. 데이터베이스는 Amazon Aurora for PostgreSQL 11.9 버전입니다.

컴포넌트

PostgreSQL 에 MyBatis를 이용하여 접속

POM

Spring Boot 프로젝트를 생성한 후 PostgreSQL JDBC 드라이버를 가져오기 위해 아래의 POM을 추가합니다.

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.0</version>
</dependency>
<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.2.20</version>
</dependency>

데이터베이스

데이터베이스에 접속하여, 주어진 SQL을 수행하여 데이터 읽기 쓰기 테스트를 위해 users 테이블과 레코드를 생성합니다. 연결 정보는 아래 설정 파일을 참조합니다.

타겟 데이터 베이스
 AWS 의 AURORA PostgreSQL :

vCPU2 RAM16 GB

엔진 11.9

테스트 용 SQL

사용자 테이블 생성 후, 아이디는 자동 증분 처리.


CREATE SEQUENCE users_seq;

create table users (
  user_id integer not null  DEFAULT nextval('users_seq'),
  user_nickname varchar(20) not null,
  user_name varchar(32) not null,
  primary key(user_id) 
);

insert into users(user_nickname, user_name) values ('1', 'user1');

설정 파일

java.main.resources 폴더 아래 config 폴더를 생성한 후 mybatis 설정 파일인 mybatis-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>
  <settings>
    <setting name="cacheEnabled" value="true" />
    <setting name="useGeneratedKeys" value="true" />
    <setting name="defaultExecutorType" value="REUSE" />
    <setting name="defaultStatementTimeout" value="3000" />
  </settings>
  <typeAliases>
    <package name="com.example.mybatis" />
  </typeAliases>
</configuration>

application.yml 에 데이터베이스 연결 정보를 구성합니다.

데이터 베이스 접속 정보를 입력하고 MyBatis 설정 파일 위치를 지정합니다.

spring:
  datasource:
    driver-class-name: org.postgresql.Driver
    url: jdbc:postgresql://~~~.cxrkmjmgkjcq.ap-northeast-2.rds.amazonaws.com:5432/
    username: postgres
    password: xxx
    initial-size: 1
    max-active: 20
    min-idle: 1
    max-idle: 20
    max-wait: 30000
    test-on-borrow: false
    test-on-return: false
    test-while-idle: true
    time-between-eviction-runs-millis: 30000
    validation-query: 'SELECT 1'
    validation-query-timeout: 3
    validation-interval: 30000
mybatis:
  config-location: classpath:config/mybatis-config.xml
  configuration:
    lazyLoadingEnabled: true
    aggressiveLazyLoading: false
    mapUnderscoreToCamelCase: true
  type-aliases-package: com.example.mybatis.repository

Main 애플리케이션

애플리케이션이 MyBatis 매퍼를 Scan 하는 폴더를 지정하는 @MapperScan("com.{compnay name}.mapper") 애노테이션에 유의합니다.

@ComponentScan(basePackages = "com.{company name}")
@MapperScan("com.{company name}.mapper")
@EnableRedisHttpSession
@SpringBootApplication
public class DemoApplication {
	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

}

세션 팩토리 설정

MyBatis를 통해 데이터베이스 연결을 위한 세션 팩토리를 구성합니다.

@Configuration
public class MybatisConfig {
	@Bean
	public SqlSessionFactory sqlSessionFactoryBean(DataSource datasource) throws Exception {
	    SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
	    sqlSessionFactoryBean.setDataSource(datasource);
	    PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
	    sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:/mapper/*.xml"));

	    return sqlSessionFactoryBean.getObject();
	  }
	
    @Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) throws Exception {
      final SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory);
      return sqlSessionTemplate;
    }
}

Mapper XML

세션 팩토리 내에서 mapper/*.xml 이라고 Mapper에 대한 위치를 지정하였습니다. Mapper xml은 Mapper Interface와 Mapper VO를 통해 데이터베이스 테이블 쿼리를 구성하는 곳입니다. XML에서 참조되고 있는 UserVO는 users 테이블 CRUD SQL에 의해 리턴 되는 결과 처리에 사용되고, UserMapper 인터페이스는 여기 xml의 id 매핑되는 메소드를 가지고 있습니다. 자바 소스에서 인터페이스 용 오브젝트를 interface 를 통해 접근합니다.

<?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..mapper.UserMapper">
    <insert id="insertUser" parameterType="com.{company name}.entity.UserVO">
        INSERT INTO users (user_nickname, user_name) VALUES ( #{userNickname}, #{userName})
    </insert>
    <update id="updateUser" parameterType="com.{company name}.entity.UserVO">
        UPDATE users 
        SET userNickname = #{userNickname}, userName = #{userName} 
        WHERE user_id = #{userId}
    </update>
    <delete id="deleteUser" parameterType="int">
        DELETE FROM users WHERE user_id = #{userId}
    </delete>
    <select id="selectOneUser" parameterType="int" resultType="com.{company name}.entity.UserVO">
        SELECT user_id userId, user_nickname userNickname, user_name userName FROM users WHERE user_id = #{userId}
    </select>
    <select id="selectAllUser" resultType="com.{company name}.entity.UserVO">
        SELECT user_id userId, user_nickname userNickname, user_name userName FROM users
    </select>
    <select id="selectTest" resultType="map">
        select schemaname||'.'||tablename from pg_tables where schemaname='public'
    </select>
</mapper>

Value Object

위에서 생성한 users 테이블의 속성을 가지는 Value Object. Lombok 사용 시 @Data 애노테이션으로 getter, setter를 생략할 수 있습니다.

@Data
public class UserVO {
	private int userId;
	private String userNickname;
	private String userName;
}

SQL mapper 인터페이스

SQL 처리 서비스 인터페이스를 정의합니다. 인터페이스의 구현체는 별도 작성하지 않고 Mapper XML을 바로 사용할 수 있습니다. @Mapper 애노테이션을 표기합니다.

@Mapper
public interface UserMapper {
    public void insertUser (UserVO user);
    public void updateUser (UserVO user);
    public void deleteUser (int userId);
    public UserVO selectOneUser (int userId);
    public List<UserVO> selectAllUser();
    public List<Map<String, Object>> selectTables();
}

테스트

POM에 JUnit과 spring-boot-starter-test 를 추가합니다.

<dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
</dependency> 
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-test</artifactId>
	<scope>test</scope>
	<exclusions>
		<exclusion>
			<groupId>org.junit.vintage</groupId>
			<artifactId>junit-vintage-engine</artifactId>
		</exclusion>
	</exclusions>
</dependency>

Users 테이블에 레코드를 입력하고 조회하는 테스트 케이스입니다.

@RunWith( SpringRunner.class ) //JUnit4
@SpringBootTest
@Slf4j
public class UserTest {
     @Autowired
    private UserMapper mapper;

    @Test
    public void userTest() {
    	UserVO user1 = mapper.selectOneUser(1);
    	
	    UserVO user = new UserVO();
	    user.setUserNickname("myNickName");
	    user.setUserName("myName");
	    mapper.insertUser(user);
	      
	  	log.info("inserted!");
    }
}

Junit 버전을 4로 지정한 후 실행합니다.

다음은 간단한 REST API 를 만들어 브라우저로 테스트하는 방법입니다.

Controller

컨트롤러는 브라우저의 요청을 처리합니다.

@RestController
@Slf4j
public class MyBatisController {
	@Autowired
	UserService service;
	
    @GetMapping(path = "/users/{id}")
	public String listUsers(@PathVariable("id") int id) {
    	UserVO user = service.selectOneUser(id);
		log.info(user.toString());		
		return user.toString();
	}
}

Service

사용자를 조회하기 위한 selectOneUser 서비스를 구현합니다.

@Service
public class UserService {
	@Autowired
	private UserMapper mapper;
	
	public UserVO selectOneUser(int userId) {
		return mapper.selectOneUser(userId);
	}
}

테스트 ( REST )

브라우저에서 http://localhost:8888/users/1 를 호출했을 때 아래 내용이 나타나면 성공입니다.

UserVO(userId=1, userNickname=1, userName=my name)

소스 위치

https://github.com/yardcrane/demo-mybatis.git - Connect to preview

profile
함께하는자

0개의 댓글