본문 바로가기
Spring/Spring Boot 게시판 만들기

[Spring Boot] Spring Boot로 MyBatis 연동하기 (MySQL) [Spring Boot 기반으로 간단한 게시판 웹사이트 만들기 - 4부]

by 임채훈 2019. 2. 24.

2019/02/24 - [Spring/Spring Boot 게시판 만들기] - [Spring Boot] UserService, BoardService 클래스 작성하기 [Spring Boot 기반으로 간단한 게시판 웹사이트 만들기 - 5부]

2019/02/24 - [Spring/Spring Boot 게시판 만들기] - [Spring Boot] User와 Board의 데이터베이스 테이블 구축 및 DTO(모델) 클래스 작성하기 [Spring Boot 기반으로 간단한 게시판 웹사이트 만들기 - 3부]

2019/02/22 - [Spring/Spring Boot 게시판 만들기] - [Spring Boot] JSP파일 만들어서 Hello Spring Boot! 출력하기 [Spring Boot 기반으로 간단한 게시판 웹사이트 만들기 - 2부]

2019/02/21 - [Spring/Spring Boot 게시판 만들기] - [Spring Boot] 이클립스(eclipse)로 Spring Boot 개발환경 구축하기 [Spring Boot 기반으로 간단한 게시판 웹사이트 만들기 - 1부]




1. MyBatis 설정정보 작성하기




- application.properties


1
2
3
4
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3307/board
spring.datasource.username=root
spring.datasource.password=root
cs



위에 작성한 내용은 기존에 Spring의 루트 컨테이너에 작성하던 아래의 코드와 동일합니다.


1
2
3
4
5
6
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
     <property name="url" value="jdbc:mysql://localhost:3307/board"></property>
     <property name="username" value="root"></property>
     <property name="password" value="root"></property>
</bean>
cs



- com.example.demo.config.MyBatisConfig.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.example.demo.config;
 
import javax.sql.DataSource;
 
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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
 
@Configuration
@MapperScan(basePackages = "com.example.demo.dao")
public class MyBatisConfig {
    
    @Bean
    public SqlSessionFactory sqlSessionFactory (DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
        
        sqlSessionFactory.setDataSource(dataSource);
        sqlSessionFactory.setTypeAliasesPackage("com.example.demo.dto");
        
        return sqlSessionFactory.getObject();
    }
    
    @Bean
    public SqlSessionTemplate sqlSession (SqlSessionFactory sqlSessionFactory) {
        
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}
cs



기존에 작성하던 코드인 아래와 동일합니다.


1
2
3
4
5
6
7
8
9
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"></property>
    <property name="typeAliasesPackage" value="model"></property>
    <property name="mapperLocations" value="classpath*:dao/mapper/**/*.xml"></property>
</bean>
    
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
</bean>
cs



조금 다른점은 Config클래스에 @MapperScan이란 어노테이션을 달아줌으로써


mapperLocations을 간단하게 설정해줄수 있습니다.





2. Dao 인터페이스와 Mapper.xml파일 작성하기



- com.example.demo.dao.UserMapper.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.example.demo.dao;
 
import java.util.List;
 
import org.apache.ibatis.annotations.Mapper;
 
import com.example.demo.dto.UserDto;
 
public interface UserMapper {
    public void insertUser (UserDto user);
    public void updateUser (UserDto user);
    public void deleteUser (String userId);
    public UserDto selectOneUser (String userId);
    public List<UserDto> selectAllUser();
}
cs



- com.example.demo.dao.BoardMapper.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.example.demo.dao;
 
import java.util.HashMap;
import java.util.List;
 
import org.apache.ibatis.annotations.Mapper;
 
import com.example.demo.dto.BoardDto;
 
public interface BoardMapper {
    public void insertBoard (BoardDto board);
    public void updateBoard (BoardDto board);
    public void deleteBoard (int num);
    public BoardDto selectOneBoard (int num);
    public List<BoardDto> selectSearchBoard (HashMap<String, Object> params);
    public List<BoardDto> selectAllBoard();
}
cs



- com.example.demo.dao.userMapper.xml


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?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.demo.dao.UserMapper">
    <insert id="insertUser" parameterType="userDto">
        INSERT INTO user VALUES (#{userId}, #{userPw}, #{userName}, #{userGender}, #{userEmail})
    </insert>
    
    <update id="updateUser" parameterType="userDto">
        UPDATE user 
        SET userPw = #{userPw}, userName = #{userName}, userGender = #{userGender}, userEmail = #{userEmail} 
        WHERE userId = #{userId}
    </update>
    
    <delete id="deleteUser" parameterType="string">
        DELETE FROM user WHERE userId = #{userId}
    </delete>
    
    <select id="selectOneUser" parameterType="string" resultType="userDto">
        SELECT * FROM user WHERE userId = #{userId}
    </select>
    
    <select id="selectAllUser" resultType="userDto">
        SELECT * FROM user
    </select>
</mapper>
cs



- com.example.demo.dao.boardMapper.xml


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<?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.demo.dao.BoardMapper">
    <sql id="title">
        <choose>
            <when test="title != null">
                #{title}
            </when>
            <otherwise>
                '제목없음'
            </otherwise>
        </choose>
    </sql>
    
    <sql id="content">
        <choose>
            <when test="content != null">
                #{content}
            </when>
            <otherwise>
                '내용없음'
            </otherwise>
        </choose>
    </sql>
    
    <insert id="insertBoard" parameterType="boardDto">
        INSERT INTO board VALUES 
        (0
        <include refid="title"/>
        <include refid="content"/>,
        #{writer}, #{password}, SYSDATE())
    </insert>
    
    <update id="updateBoard" parameterType="boardDto">
        UPDATE board SET 
        title = <include refid="title"/>,
        content = <include refid="content"/>,
        writer = #{writer}, password = #{password} 
        WHERE num = #{num}
    </update>
    
    <delete id="deleteBoard" parameterType="int">
        DELETE FROM board WHERE num = #{num}
    </delete>
    
    <select id="selectOneBoard" parameterType="int" resultType="boardDto">
        SELECT * FROM board WHERE num = #{num}
    </select>
    
    <select id="selectSearchBoard" parameterType="java.util.HashMap" resultType="boardDto">
        SELECT * FROM board
    </select>
    
    <select id="selectAllBoard" resultType="boardDto">
        SELECT * FROM board
    </select>
</mapper>
cs



boardMapper.xml 파일에서는 제목 또는 내용을 작성하지 않고 게시글을 등록할때


'제목없음', '내용없음' 문구로 데이터베이스에 추가될수 있도록 추가해주었고


53번째 줄 selectSearchBoard은 여러개의 파라미터를 받아와서 게시글을 select 해주고


파라미터들이 어떤 상황에서는 넘어오고 어떤상황에서는 넘어오지 않고 상황에 따라 달라서


파라미터를 HashMap 타입으로 받도록 설정해 주었습니다.


selectSearchBoard의 쿼리문은 추후에 게시판 기능을 실제로 구현할때


추가적으로 작성하도록 하겠습니다.




3. 작성 완료된 코드 테스트



테스트는 Spring Test 기능을 통해 테스트합니다.



- com.example.demo.DemoApplicationTests.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.example.demo;
 
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
import com.example.demo.dao.BoardMapper;
import com.example.demo.dao.UserMapper;
import com.example.demo.dto.BoardDto;
import com.example.demo.dto.UserDto;
 
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class DemoApplicationTests {
 
    @Autowired
    private UserMapper uMapper;
    @Autowired
    private BoardMapper bMapper;
    
    @Test
    public void userTest() {
        UserDto user = new UserDto();
        user.setUserId("test");
        user.setUserPw("test");
        user.setUserName("테스트");
        user.setUserGender("남");
        user.setUserEmail("test@test.test");
        uMapper.insertUser(user);
        
        System.out.println(uMapper.selectOneUser("test"));
    }
    
    @Test
    public void boardTest() {
        BoardDto board = new BoardDto();
        board.setPassword("1234");
        board.setWriter("test");
        bMapper.insertBoard(board);
        
        System.out.println(bMapper.selectOneBoard(1));
    }
    
}
cs




위와 같이 테스트코드 작성 후 Ctrl + F11키를 눌러 실행을 했을때


콘솔창에 아래와 같이 출력이 된다면 성공적으로 끝난겁니다.


또한 title과 content를 따로 설정해주지 않았을때 각각 '제목없음'과 '내용없음'으로 출력되는걸 확인할 수 있습니다.











다음장에서는 실제로 사용될 기능들인 회원가입, 로그인, 게시글 쓰기, 수정 등을 


service클래스에 작성해보도록 하겠습니다.





+ 추가내용



다음과 같은 오류가 발생할수가 있습니다.




mysql 서버의 timezone과 관련된 오류인데 mysql Driver 버전이 5.1.X버전부터 발생할수 있다고하는데


이 프로젝트의 mysql 드라이버가 아래와 같이 버전 8.0.15로 설정이 되어있는걸 확일할 수 있습니다.





timezone이 뭔지, 그로인해 왜 오류가 발생하는지 궁금하시면 개인적으로 찾아보시면 되겠고 


아무튼 저 오류를 해결하는 방법은




1. 본인 PC에 설치된 mysql의 timezone을 임의로 설정해주는 방법


1
SET GLOBAL time_zone = '+3:00'
cs



해당 코드를 mysql DB 콘솔창에 입력해줍니다.





2. mysql Driver의 버전을 임의로 지정해주는 방법




두가지 방법으로 해당 오류 해결이 가능합니다.


그러나 보시다시피 노란줄이 끄여있는걸로 보아 Spring Boot에서 버전을 직접 지정해주는걸 권장하지 않는다고 생각해볼수 있습니다.



댓글