프로젝트에 DB연결

jungnoeun·2022년 9월 16일
0

spring

목록 보기
11/24

🚲목표

  • Spring boot와 MySQL 데이터베이스 연결
  • mybatis를 이용

mybatis 장점

mybatis는 sql명령어를 관리해주는 편리한 라이브러리이다.
sql명령어를 매번 문자열로 지정해서 하나하나 적어주는 방식보다 유지보수가 좋고, 효율성이 좋다. 그래서 mybatis를 통해 관리해줄 것이다.

1.Gradle spring 개발환경 설정

	// https://mvnrepository.com/artifact/org.mybatis/mybatis
	implementation group: 'org.mybatis', name: 'mybatis', version: '3.5.7'
	// https://mvnrepository.com/artifact/org.mybatis/mybatis-spring
	implementation group: 'org.mybatis', name: 'mybatis-spring', version: '2.0.6'
	// https://mvnrepository.com/artifact/org.springframework/spring-jdbc
	implementation group: 'org.springframework', name: 'spring-jdbc', version: '5.3.22'

mybatis와 mybatis를 연동하는 스프링, 스프링과 jdbc를 연결하는 라이브러리이다.

  • mybatis는 데이터베이스를 이용하는 sql문을 설정하는 라이브러리이기 때문에 데이터베이스 개발환경이 필요하다.
  • 스프링 jdbc와 mybatis를 연결하는 mybatis-spring 라이브러리가 필요하다.

이를 그림으로 표현하면 아래와 같다.



2.스프링에서 관리하는 빈 파일 생성

스프링 프레임워크에서 관리하는 일종의 설정 규칙을 만드는 것이다.

DataSource

  • 데이터베이스에서 데이터 풀을 가져오는 설정이다.

sqlSessionFactory

  • 만들어진 데이터 풀을 통해 sql문을 관리하는 공장을 만드는 것이다.

sqlSession

  • sqlSessionFactory라는 공장에서 관리하는 생성자를 하나하나 정의하는 코드이다.

  • <property> 가 아닌 <constructor>를 쓰면 공장에서 생성자를 만들어 사용하겠다는 의미이다.


MyBatis와 HikariCP 연동을 위한 설정 클래스

@Configuration
@PropertySource("classpath:/application.properties")
@MapperScan(value = "hello.board.mapper")
// MyBatis와 HikariCP 연동을 위한 설정 클래스
public class DBConfig {

    @Autowired
    private ApplicationContext applicationContext;

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.hikari")
    public HikariConfig hikariConfig() {
        return new HikariConfig();
    }

    // HikariCP를 이용해 DB 접속, 데이터풀을 가져옴
    @Bean
    public DataSource dataSource() throws Exception{
        DataSource dataSource = new HikariDataSource(hikariConfig());
        return dataSource;
    }

    // MyBatis 설정 관련 빈, 데이터풀에서 sql문을 관리하는 공장
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception{
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        // DB(Mysql)에서 읽어온 데이터를 담아올 도메인(DTO)의 패키지 경로를 설정 -> Mapper 파일에 편하게 클래스 명만 작성해서 사용
        sqlSessionFactoryBean.setTypeAliasesPackage("hello.board.domain");
        // 쿼리를 작성할 mapper 파일을 생성해 둘 경로(resources/mapper) -> 해당 경로에. xml로 끝나는 파일들을 스캔해서 설정
        sqlSessionFactoryBean.setMapperLocations(applicationContext.getResources("classpath:/mapper/*.xml"));
        return sqlSessionFactoryBean.getObject();
    }

    // 장에서 관리하는 하나하나의 생성자를 정의, SqlSessionTemplate은 SqlSession을 구현
    @Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

}

MapperScan 인터페이스 생성

mapper는 매핑이라는 단어에서 유추할 수 있듯이 sql문(xml)을 메소드(java)로 매핑 시켜주는 것을 의미한다.

@Component
@MapperScan
public interface TestMapper {
    Test test() throws Exception;
}

mapper와 mapperscan차이

@mapper로 하나씩 매퍼를 등록할 수 있지만, @mapperScan으로 클래스패스를 지정해서 myBatis-sping 연동 모듈의 자동스캔기능을 사용할 수 있다.
@mapperScan의 사용은 다음과 같이 한다.

@Configuration
@MapperScan("org.mybatis.spring.sample.mapper")
public class AppConfig {
  // ...
}




3.Mapper XML 생성

쿼리를 작성할 매퍼 xml을 2의 설정파일에 지정한 경로에 생성한다.

  • mapper namespace값은 Mapper Interface와 같게 한다.
  • id는 Mapper Interface 클래스에서 선언한 메서드의 이름과 동일하게 맞춰준다.
  • reources/mapper/TestMapper.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.test.api.mapper.TestMapper">

    <select id="test" parameterType="map" resultType="Test">
        SELECT * FROM ${tblBoard}
    </select>

</mapper>



4.Service 생성

Mapper Interface를 주입받아 사용할 서비스를 생성

@Service
public class TestService {
    private final TestMapper testMapper;

    @Autowired
    public TestService(TestMapper testMapper) {
        this.testMapper = testMapper;
    }

    public Test test() throws Exception {
        return testMapper.test();
    }
}



5.Controller 생성

테스트 및 서비스를 사용하기 위해 컨트롤러를 생성

@RestController
public class TestController {
    private final TestService testService;

    @Autowired
    public TestController(TestService testService) {
        this.testService = testService;
    }

    @GetMapping(value = "/test")
    public Test test() throws Exception {
        return testService.test();
    }
}



6.추가

6-1.DBConfig.java에 ConfigLocation 추가

mybatis는 sql을 관리하는 만큼 sql의 관리 설정이나, sql문을 정의한 문서가 필요하여 만들어주었다.

// ---------추가----------
        sqlSessionFactoryBean.setConfigLocation(applicationContext.getResource("classpath:/mybatis-config.xml"));
        // ------ 추가 끝 ------------

mybatis-config.xml 생성

이 문서에서 테이블이름이나, 컬럼의 이름을 변수화 시켜주는 설정을 한다.

  • value 부분은 테이블 구조의 실제 column 이름이고, name은 이제부터 mybatis 안에서 사용될 column의 이름이다
  • typeAliases는 이러한 모델 객체를 어디서 가져올 것이나의 경로를 의미한다. 즉 모델 클래스 경로를 지정해주면 된다.
  • 이때 모델객체도 이런식으로 mysql데이터베이스의 컬럼이름과 맞춘다.
  • 이와같이 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>
    <properties>
        <property name="tblBoard" value="test_board" />
        <property name="colBno" value="bno" />
        <property name="colTitle" value="title" />
        <property name="colContent" value="content" />
        <property name="colUserid" value="userid" />
    </properties>

    <typeAliases>
        <package name="hello.board.domain" />
    </typeAliases>
</configuration>

database(board)에 table(TEST_BOARD) 생성

6.2 실행시 java.sql.SQLException: No database selected 오류 발생

applicatioin.properties에서 DB주소에 스키마 이름이 빠져 있어서 생긴 오류이다.

# 변경 전
spring.datasource.hikari.jdbc-url=jdbc:mysql://localhost:3306/?autoReconnect=true&useSSL=false&amp&serverTimezone=UTC
# 변경 후
spring.datasource.hikari.jdbc-url=jdbc:mysql://localhost:3306/board?autoReconnect=true&useSSL=false&amp&serverTimezone=UTC

참고사이트:
http://blog.iotinfra.net/?tag=no-database-selected

1개의 결과 받기 성공 실행 결과




6-3.TooManyResultsException 예외 발생

select 실행결과 받아야하는 값이 2개이상일때 TooManyResultsException 에러가 발생했다.
해결방법
1. 그래서 interface TestMapper, TestController코드, TestService의 코드들에서 test함수의 반환값을 Test에서 List<Test>로 바꿔주었다.
2. 또한 sql문을 작성하는 resource.mapper.TestMapper.xml<select>의 resultType을 Test에서 Map으로 바꿔주었다.

<!-- resource.mapper.TestMapper.xml -->
<select id="test" parameterType="map" resultType="Map">
        SELECT * FROM ${tblBoard}
    </select>

🌞 참고로 resource.mapper.TestMapper.xml<select>의 resultType만 바꿔주면 되는건가 싶어서 test메서드의 반환값을 Test로 바꿔보았지만 UnsatisfiedDependencyException 에러가 발생하였다. ㅅtest메서드의 반환값은List<Test>으로 하는것이 맞는듯하다.
🤗 추가로 test메서드의 반환값은 List<Test>로 해주고 select 문의 resultType을 Test로 바꿔주었더니 에러 없이 두개 이상의 값을 받아 올 수 있었다. 그 이유는 한 행(SELECT * FROM ${tblBoard})을 객체로 보기 때문에 한 행을 객체 Test로 차곡차곡 담은 뒤 mybatis가 알아서 리스트로 넣어주기 때문이다.

두개이상의 결과값 받기 성공 실행 결과

참고 사이트
https://www.devkuma.com/docs/mybatis/%EC%97%AC%EB%9F%AC-%EA%B0%9C%EC%9D%98-%EA%B2%B0%EA%B3%BC-%EC%96%BB%EA%B8%B0/
https://m.blog.naver.com/zxxne/222476370039







mapperScan
https://codingnojam.tistory.com/27
https://mybatis.org/spring/ko/mappers.html
DB 연결
https://veneas.tistory.com/entry/Spring-Boot-MyBatis-%EC%82%AC%EC%9A%A9%EB%B2%95-Mapper-MapperScan?category=881419
https://meaownworld.tistory.com/28
DB 커넥션 연결 설정
https://linked2ev.github.io/gitlog/2019/08/21/springboot-mvc-4-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-MyBatis-+-HikariCP-+-MariaDB-%EC%84%A4%EC%A0%95/
SqlSessionTemplate과 SqlSession
https://mybatis.org/spring/ko/sqlsession.html
hikariCP 연결 관련인듯??
https://frontierdev.tistory.com/215

profile
개발자

0개의 댓글