IT'S DO
article thumbnail
728x90

1. mapper.java , mapper.xml 경로 잘 잡아줌

2. mapper.xml id와 mapper.java id 잘 잡아줌.

3. result type 문제. 다 바꿔 주고 테스트 해봤으나 아님.

 

위와 같은게 대부분이라서 인터넷에선 저런 부분들 해결만 나옴. 

 

#다른 문제 : 

 

Invalid bound statement (not found): com.example.dmf.weather.service.WeatherService.findAll

 

원인.

2022.11.30 : 한마디로 말하면 해결이 안됐다.

2022-12-01 : 해결됨

public class WeatherServiceImpl implements WeatherService

Service interface로 두고, serviceImpl로 구현해서 해당 부분을 mybatis로 받으니 에러가 나타남.

 

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

 

그래서 controller에서 

@RestController
@RequestMapping(value = "/api/v1/app/")
public class WeatherApiController {

    @Autowired
    private WeatherMapper weatherMapper;

    @Autowired
    private WeatherService weatherService;

    @Autowired
    private WeatherServiceImpl weatherServiceImpl;

    @RequestMapping(value= "findAll", method = RequestMethod.POST)
    public ResponseEntity<?> findAll() throws Exception {
        WeatherResponseDto weatherResponseDto = new WeatherResponseDto();
        weatherResponseDto.setResultCode("S0001");
        weatherResponseDto.setRes(weatherService.findAll());
        return new ResponseEntity<>(weatherResponseDto, HttpStatus.OK);

    }
}

으로 하면

Invalid bound statement (not found): com.example.dmf.weather.service.WeatherService.findAll 에러가 나타남.

 

하지만 

 

@RestController
@RequestMapping(value = "/api/v1/app/")
public class WeatherApiController {

    @Autowired
    private WeatherMapper weatherMapper;

    @Autowired
    private WeatherService weatherService;

    @Autowired
    private WeatherServiceImpl weatherServiceImpl;

    @RequestMapping(value= "findAll", method = RequestMethod.POST)
    public ResponseEntity<?> findAll() throws Exception {
        WeatherResponseDto weatherResponseDto = new WeatherResponseDto();
        weatherResponseDto.setResultCode("S0001");
        weatherResponseDto.setRes(weatherServiceImpl.findAll());
    /*    weatherResponseDto.setRes(weatherService.findAll()); */
        return new ResponseEntity<>(weatherResponseDto, HttpStatus.OK);

    }
}

로 하면 실행이 잘됨.

 

정확한 원인은 모르겠으나, 구글링을 뒤진 결과로는 

dto , dao , mapper 등으로 mapper.xml을 통한 값을 들고 왔으면, 거기서 직접적인 호출이 이루어져야 한다고한다.

 

아직은 해결이 안됐으나, 추후에 해결이 된다면 다시 수정해서 글을 올리도록 함.

 

아니면 해결 방법을 아시는 분 있으시면 댓글 남겨주시면 감사히 세겨듣도록 하겠습니다.

 

 

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

 

# 해결

 

해결이라고 하면 위를 완벽히 해결 한건 아닌데, service로 인터페이스를 만들고 serviceImpl 구현을 해도 잘 불러와 지기 때문에. 해결이라고 하고 쓴다.

 

위와 같이 직접적인 호출이 이루어져야 한다고 했는데, 직접적인 호출로 이루어지게끔 다시 바꿈에도 불구하고 

위 처럼 에러가 발생함. 그래서 아예 내가 셋팅을 잘못 했다고 생각하게됨.

 

1. 

MyBatisConfig.java를 기존에 

package com.example.dmf.config;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration
// 패키지명
@MapperScan(value = "com.example.dmf", sqlSessionFactoryRef = "SqlSessionFactory")
public class MyBatisConfig {

    @Value("${spring.datasource.mapper-locations}")
    String mPath;

    @Bean(name = "dataSource")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource DataSource() {
        return DataSourceBuilder.create().build();
    }


    @Bean(name = "SqlSessionFactory")
    public SqlSessionFactory SqlSessionFactory(@Qualifier("dataSource") DataSource DataSource, ApplicationContext applicationContext) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(DataSource);
        sqlSessionFactoryBean.setMapperLocations(applicationContext.getResources(mPath));
        sqlSessionFactoryBean.setConfigLocation(applicationContext.getResource("classpath:mybatis-config.xml"));
        return sqlSessionFactoryBean.getObject();
    }

    @Bean(name = "SessionTemplate")
    public SqlSessionTemplate SqlSessionTemplate(@Qualifier("SqlSessionFactory") SqlSessionFactory firstSqlSessionFactory) {
        return new SqlSessionTemplate(firstSqlSessionFactory);
    }

}

을 사용해주었다. 하지만 인터넷 찾아보니, 약간 오버 셋팅 같은 느낌이라서 아예 없애버렸다.(지우게됨)

 

2. build.gradle.kts

(코틀린 버전이라서 이거인데, 기존 build.gradle은 그냥 적혀있는거 대로 쓰고 아래 필요한org.mybatis.spring.boot만 쓰자)

implementation("org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.2") /* mybatis */

 

3. Mapper.xml

resources/mapper/BoardMapper.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.example.dmf.mapper.BoardMapper">
    <select id="selectBoardList" resultType="com.example.dmf.board.dto.BoardDto">
     <![CDATA[
        SELECT
            board_idx,
            title,
            hit_cnt
        FROM
            t_board
        WHERE
            delete_yn = 'N'
        ORDER BY board_idx DESC
        ]]>
  </select>
</mapper>

그 다음으로 중요한 것은 id => interface와 맞춰줘야함. namespace => 마찬가지로 인터페이스와 맞춰줘야함.

resultType은 

-> select -> resultType  -> 담길 그릇

-> insert -> parameterType -> String, int 등 ~ 형식이 들어올 것이다 라고 알려주는 것. 이다.

Dto로 받을거라서 위에처럼 지정. Dto로 받는 이유가 있다면, jsonData로 깔끔하게 값을 받게끔이 큰 이유인거 같음.

 

4. service (interface)

import com.example.dmf.board.dto.BoardDto;

import java.util.List;

public interface BoardService {
    List<BoardDto> selectBoardList() throws Exception;

}

 

5. serviceImpl (구현)

import com.example.dmf.board.dto.BoardDto;
import com.example.dmf.mapper.BoardMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class BoardServiceImpl implements BoardService{

    @Autowired
    private BoardMapper boardMapper;

    @Override
    public List<BoardDto> selectBoardList() throws Exception {
        return boardMapper.selectBoardList();
    }
}

 

6. controller

import com.example.dmf.board.dto.BoardDto;
import com.example.dmf.board.service.BoardService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.List;

@Controller
public class BoardController {

    @Autowired
    private BoardService boardService;

    @RequestMapping("/apple")
    public ModelAndView openBoardList() throws Exception{
        ModelAndView mv = new ModelAndView("thymeleaf/apple/boardList");

        List<BoardDto> list = boardService.selectBoardList();
        mv.addObject("list",list);

        return mv;
    }
}

 

 

7. application.yml

mybatis:
  mapper-locations: classpath:mapper/*.xml

 

으로 해주니 

성공됨.

profile

IT'S DO

@멋진놈

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!