본문 바로가기

스프링부트를 이용한 웹페이지 만들기 도전!!/이클립스 버전

SPRING BOOT를 이용한 나의 첫 웹페이지 제작 (5) - application, mysql , dto, dao(mapper),mybatis

이제 패키지들과 view폴더를 만들었으니 그 안의 내용물들을 알차게 추가해서 Mysql db와 연동해서 db안의 내용을 웹 페이지에 띄워주는 작업을 진행 할 것이다.

 

1. 일단, db와 연동을 하려면 당연히 mysql db가 작성이 되어 있어야 한다.

그렇다면 Mysql을 설치하고 스키마 정의, 테이블 정의 를 해주어야 한다.

Mysql을 도스창으로 사용하던지, 나처럼 workbench를 이용하던지는 상관 없다. 

게시판 사용자의 이름,성별,id,pw 등을 저장하는 user 테이블과

게시물의 제목,내용,작가,pw,게시일을 저장하는 board테이블을 만들어주자.

 

이렇게 테이블을 만들었으면 이제 해야할 일은 이클립스를 이용해 만든 웹 페이지에서

정보를 입력 받으면 그 정보가 Mysql의 db에 쌓이게 하고

또한, 웹사이트가 Mysql의 db에서 게시물에 관련된 정보를 꺼내와서 사이트에 띄울 수 있게 만들어야 한다.

이를 위해서 우리는 사전에 만들어 놓았던 패키지들에 컨트롤러,jsp파일,dto,dao,mybatis 등을 이용해 나갈 것이다.

지금부터 순서대로 진행할테니 잘 따라오길 바란다.

2. dto클래스 작성 , dao Mapper인터페이스와 MapplerXML 작성

 

DTO(Data Tranfer Object) 란 ? - 풀 네임에서 유추할 수 있듯이 데이터를 객체로 만들어주는 클래스이다.

우리가 Mysql에 테이블의 형태로 만든 데이터들을

import com.example.demo.dto.BoardDto로 import하고 

BoardDto board 이렇게 객체를 선언해주면

board.setTitle("제목") 이런식으로 객체화하여 사용할 수 있게 된다.

 

DAO(Data Access Object) 란 ? - 데이터 베이스에 접속해서 데이터 추가, 삭제, 수정 등의 작업을 하는 클래스

일반적인 JSP 혹은 Servlet 페이지내에 위의 로직을 함께 기술할 수 도 있지만, 유지보수 및 코드의 모듈화를 위해 별도의 DAO클래스를 만들어 사용 한다. 실제로 DB에 insert,update,delete등의 작업을 해주는 클래스라고 보면 될듯하다.

참고로, 우리는 JDBC가 아닌 Mybatis를 사용할 것이다.

Mybatis나 JDBC나 모두 웹 프로그램을 DB와 접속시켜주는 기능을 하는데

JDBC의 복잡성을 Mapping으로 개선하여 쉽게 사용하게 만들어주는게 Mybatis의 기능이다.

따라서 dao클래스를 따로 만들지 않고, 우리는 dao패키지 안에 Mapper들을 만들어서 DB의 값들에 대한

인서트, 딜리트, 업데이트를 진행 할 것이다. Mapper는 인터페이스와 이를 구현한 XML 2개의 파일로 이루어진다.

 

그렇다면 다음과 같은 형식으로 유저,게시판각각의 dto와 Mapper를 선언해서 각 패키지에 넣도록 하자.

DAO.java가 아닌, Mapper.java와 Mapper.xml이 저장되어 있는 모습

 

BoardDto.java

package com.example.demo.dto;
import java.util.Date;

public class BoardDto {
 private int num;
 private String title;
 private String content;
 private String writer;
 private String password;
 private Date writeDate;
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getWriter() {
return writer;
}
public void setWriter(String writer) {
this.writer = writer;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getWriteDate() {
return writeDate;
}
public void setWriteDate(Date writeDate) {
this.writeDate = writeDate;
}
public String toString() {
    return "BoardDto [num=" + num + ", title=" + title + ", content=" + content + ", writer=" + writer
            + ", password=" + password + ", writeDate=" + writeDate + "]";
}
 
}

UserDto.java

package com.example.demo.dto;

public class UserDto {
private String userId;
private String userPw;
private String userName;
private String userGender;
private String userEmail;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserPw() {
return userPw;
}
public void setUserPw(String userPw) {
this.userPw = userPw;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserGender() {
return userGender;
}
public void setUserGender(String userGender) {
this.userGender = userGender;
}
public String getUserEmail() {
return userEmail;
}
public void setUserEmail(String userEmail) {
this.userEmail = userEmail;
}
public String toString() {
return "UserDto [userId=" +userId + ",UserPw="+userPw+"UserName="+userName+"UserGender="+userGender+"UserEmail="+userEmail+"]";
}

}

UserMapper.java

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();

}

 

BoardMapper.java

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();
}

UserMapper.java
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();

}

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.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>

 

UserMapper.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.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>

3. 이렇게 dto와 dao의 작성이 완료되었으면 이제 mybatis가 dto와 dao를 활용할 수 있도록 MybatisConfig클래스를 만들어야 한다. 위치는 com.example.demo.config패키지에 저장하면 된다.

 

MyBatisConfig.java

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);
	}

}

그리고, 다음과 같은 4줄의 코드를 application.properties에 추가해준다.

 

 

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.datasource.url=jdbc:mysql://localhost:3306/board(스키마(db)이름^^)

spring.datasource.username=root(여러분의 것^^)

spring.datasource.password=pw (여러분의 것^^)

 

딱 보자마자 알 수 있듯이 내가 가지고 있는 MysqlDB와 연동해주기 위한 드라이버, url주소, 아이디, 비밀번호 이다.

그렇다면 지금까지 한 것들을 정리해보자.

1. 이클립스와 연동하기위한 DB작성(스키마+user와board테이블)

 

2. DB를 객체화 하기 위한 dto클래스와 mapper작성(mapper클래스+mapper.xml)

 

3. mapper를 mybatis가 알아들을 수 있게 서로 연동해주는 MybatisConfig클래스 작성

 

이제 DB와 연동하기위한 모든 준비는 끝났다.

 

실제로 웹페이지를 만들때는 JSP VIEW를 이용해서 웹상으로 상호작용하며 DB를 만지겠지만

 

일단은 지금까지 잘 따라왔는지 확인하기 위해서 VIEW를 생략하고 단순 어플리케이션만 이용해서 DB를 수정하는 작업을 진행해 보겠다.

 

 

어플리케이션의 형태는 아래의 코드와 같다.

 

@SpirngBootApplication은 여러가지 어노테이션이 혼합되어있는 어노테이션 인데 중요한 것 2가지만 뽑자면

   -@Componentscan

 @Service, @Repository, @Controller 등의 어노테이션을 스캔해서 Bean으로 만들어주는 어노테이션

 패키지내의 application.property를 검색하는 것도 이 어노테이션이 수행한다.

   -@EnableAutoConfiguration

 사전에 등록한 라이브러리들을 자동으로 Bean으로 만들어주는 어노테이션

   - @Configuration

 빈에 대해서 Context에 추가하거나 특정 클래스를 참조해온다

 

따라서 이 어노테이션에 의해서 아까 위에서 설정했던 url, id, pw,드라이버의 정보를 활용하게 되는 것이다.

코드의 내용은 단순하다. user테이블에 내용들을 넣고 board테이블에 내용들을 넣고 넣은 정보들을 출력해준다.

 

package com.example.demo;
 
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.example.demo.dao.BoardMapper;
import com.example.demo.dao.UserMapper;
import com.example.demo.dto.BoardDto;
import com.example.demo.dto.UserDto;
 
@SpringBootApplication
public class HaounApplication {
 
    private UserMapper uMapper;
    private BoardMapper bMapper;
    
    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"));
    }

    public void boardTest() {
        BoardDto board = new BoardDto();
        board.setPassword("1234");
        board.setTitle("haoun blog");
        bMapper.insertBoard(board);
        System.out.println(bMapper.selectOneBoard(1));
    }
    
}

 

아직 이 어플리케이션을 직접 실행시킬수는 없고 Junit이라는 기능을 활용해서 테스트를 진행 할 것이다.

 

src/test/java의 com.example.demo폴더에 이와 똑같은 코드를 작성한다.

다만, 테스트를 위한 코드라는 것을 명시하기 위해서 몇가지 어노테이션이 붙어줘야한다.

 

@ExtendWith(SpringExtension.class)는

junit4의 @RunWith(SpringJUnit4ClassRunner.class)와 똑같은 것이다.

나도 아직까지 정확한 의미는 이해를 못 했지만, 간략하게 설명하자면

junit으로 테스트를 하는 도중에 ApplicationContext를 관리해주는 스프링 컨테이너의 확장을 담당한다고 생각하면 될 것같다.@Autowired는 해당 변수에 Bean을 주입해준다.@Test는 테스트 대상을 지정해준다.@ignore로 생략하거나 @beforeall, @beforeeach, @afterall, @aftereach로 순서를 정해서 실행할 수도 있다.

 

package com.example.demo;
 
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import com.example.demo.dao.BoardMapper;
import com.example.demo.dao.UserMapper;
import com.example.demo.dto.BoardDto;
import com.example.demo.dto.UserDto;
 
@ExtendWith(SpringExtension.class)
@SpringBootTest
public class HaounApplicationTests {
 
    @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.setTitle("haoun blog");
        bMapper.insertBoard(board);
        System.out.println(bMapper.selectOneBoard(1));
    }
    
}

 

별 문제없이 잘 따라왔다면 아래와 같이 작업을 finish하고 insert한 튜플을 콘솔에 출력하는게 중간에 들어가 있고

Mysql을 확인해보면 DB에 알맞게 값이 들어왔음을 확인할 수 있을것이다.