Post Entity, DTO 들을 만들고 생성 테스트를 진행한 뒤에 Post Controller와 Service를 생성하고 PostMapper에 Mapper 어노테이션 작성과 Mapper.xml 작성을 완료한 후 Teliend API를 통한 테스트를 진행하였다.

 

그런데.. POST 요청 보냈더니 이러한 에러가 발생하였다.

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.somaeja.post.mapper.PostMapper.save
at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:235) ~[mybatis-3.5.5.jar:3.5.5]
at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:53) ~[mybatis-3.5.5.jar:3.5.5]
at org.apache.ibatis.binding.MapperProxy.lambda$cachedInvoker$0(MapperProxy.java:115) ~[mybatis-3.5.5.jar:3.5.5]
at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1705) ~[na:na]
at org.apache.ibatis.binding.MapperProxy.cachedInvoker(MapperProxy.java:102) ~[mybatis-3.5.5.jar:3.5.5]
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:85) ~[mybatis-3.5.5.jar:3.5.5]
at com.sun.proxy.$Proxy54.save(Unknown Source) ~[na:na]
at com.somaeja.post.service.PostService.savePost(PostService.java:20) ~[classes/:na]
...
...
...

2시간 정도 고생을 하다보니 설정된 코드에서 문제점을 발견하였다...

 

 

문제점

@EnalbeAutoConfiguration <- 문제점 
@MapperScan(basePackages = "com.somaeja")
public class PersistenceConfig {
        <- 문제점 
}

 

문제점 파악.

 

@EnableAutoConfiguration 은 Spring Boot 관련 자동 구성 어노테이션이었는데,

Dependencies > spring-boot-autoconfigure > META-INF > spring.factories

디렉터리 내부의 Definition 들을 Bean으로 등록해 준다고 하여서 configuration 대신에 사용하였었다.

 

ContextLoad Test

@SpringBootTest
class MainApplicationTests {
    @Test
    void contextLoads() {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(PersistenceConfig .class);
        String[] beanDefinitionNames = ac.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println("beanDefinitionName = " + beanDefinitionName);
        }
    }
}

ContextLoad 테스트를 진행하였을 때에도 Datasource, sqlSessionFactory, postMapper 빈이 등록되어 있어 문제가 없다고 판단하였지만, 사실은 Mybatis 설정이 적용되지 않은 sqlSessionFacroty와 Root Context (MainApplication.class)에 등록되지 않은 postMapper 이였다는 것을 알지 못하였고, 헤맬 수밖에 없었다.

 

 

문제 해결 방법.

@Configuration // @EnableAutoConfiguration 에서 Configuration 으로 변경
@MapperScan(basePackages = "com.somaeja")
public class PersistenceConfig {

    // Custom Initializer -> Mybatis MapperLocations 설정이 적용된 SqlSessionFactory 생성 
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        final SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource);

        // 스프링에서 Xml 파싱을 통한 Bean 생성시 사용하는 PathMatchingResourcePatternResolver 를 사용
        // 하여 classpath: 패턴의 경로를 작성하고 Mapper Location에 설정하였다.
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sqlSessionFactory.setMapperLocations(resolver.getResources("classpath:mybatis/mapper/*.xml"));
        return sqlSessionFactory.getObject();
    }

}

 

참고 문서

MyBatis - 마이바티스 3 | 소개

MyBatis - 마이바티스 3 | 매퍼 XML 파일

Mybatis-Spring-Boot-Starter 소개 문서 번역

'프로젝트' 카테고리의 다른 글

Mybatis의 IndexOutOfBoundsException?  (2) 2021.01.12
Spring Boot Gradle Test 실패?  (0) 2020.12.31
[Somaeja : 소매자] 01. 프로젝트 개요  (0) 2020.11.15

+ Recent posts