스프링부트 게시판 만들기 제6강. Database Access

 

스프링 부트 게시판 만들기

제6강 Database Access

 

 

오늘은 데이터베이스에 접근하는

DAO(Data Access Object)와 mapper xml에 대해 알아보겠습니다.

먼저 지난 5강에서 BoardarticleSvcImpl의 in 메소드를 다시 보겠습니다.

 

	@Autowired BoardarticleDao boardarticleDao; //--- Dao 빈 주입

	@Override
	public boolean in( HttpServletRequest request, Map<String, Object> param, ModelMap model )throws Exception{

		Map<String, Object> svcMap = new HashMap<>();
		
		//---* 게시글 저장
		svcMap.put( "title", param.get("title") );
		svcMap.put( "content", param.get("content") );
		svcMap.put( "readcnt", 0 );
		svcMap.put( "commentcnt", 0 );
		svcMap.put( "recommendcnt", 0 );
		svcMap.put( "groupnum", 0 );
		svcMap.put( "levelnum", 0 );
		svcMap.put( "stepnum", 0 );
		svcMap.put( "inip", request.getRemoteAddr() );

		boardarticleDao.in( svcMap );
		//--- 게시글 저장 끝
		
		//---* 그룹번호 업데이트
		int seq = Integer.parseInt( svcMap.get( "seq" ).toString() );
		svcMap.put( "seq", seq );
		svcMap.put( "groupnum", seq );
		
		boardarticleDao.up( svcMap );  //---up method 실행
		//---* 그룹번호 업데이트 끝
		
		return true;
	}

 

위의 boardarticleDao.In( svcMap )이 실행되면서 BoardarticleDao로 흐름이 넘어 갑니다.

 

자 그럼 BoardarticleSvc에 대한 설명은 지난 강의를 참고하시고 

오늘의 주인공 DAO(Data Access Object)를 확인해보겠습니다.

일단 Dao도 Service 파일처럼

Dao Interface파일을 만들고 상속받아 구현하도록 하겠습니다.

 

package com.soledot.board.boardarticle;

import java.util.List;
import java.util.Map;

/**
 * @author soledot
 * @since 20191108
 * @version soledot
 * @description boardarticle Dao Interface
 *
*/

public interface BoardarticleDao {

	//---*카운트(Map)
	public int cnt( Map<String, Object> param );

	//---*삭제
	public int del( Map<String, Object> param );

	//---*수정
	public Map<String, Object> edit( Map<String, Object> param );

	//---*저장
	public int in( Map<String, Object> param );

	//---*리스트
	public List<Map<String, Object>> list( Map<String, Object> param );

	//---*one row
	public Map<String, Object> one( Map<String, Object> param );

	//---*업데이트
	public int up( Map<String, Object> param );

}

 

interface BoardarticleDao 입니다.

Method명이 직관적이지 않나요? 굳이 설명하지 않아도 어떤 역할을 하시는 지는 알것같은데...

나만 그런겨?

그럼 BoardarticleDao 를 상속받은 BoardarticleDaoImpl을 보겠습니다.

 

package com.soledot.board.boardarticle;

import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

/**
 * @author soledot
 * @since 20191108
 * @version soledot
 * @description boardarticle Dao 구현 클래스
 *
*/

@Repository("BoardarticleDao")
public class BoardarticleDaoImpl implements BoardarticleDao {

	@Autowired private SqlSession sqlSession;

	//---*카운트(Map)
	@Override
	public int cnt( Map<String, Object> param ){
		return sqlSession.selectOne( "boardarticle.cnt", param );
	}

	//---*삭제
	@Override
	public int del( Map<String, Object> param ){

		return sqlSession.delete( "boardarticle.del", param );
	}

	//---*수정
	@Override
	public Map<String, Object> edit( Map<String, Object> param ){
		return (Map<String, Object>)sqlSession.selectOne( "boardarticle.edit", param );
	}

	//---*저장
	@Override
	public int in( Map<String, Object> param ){
		return sqlSession.insert( "boardarticle.in", param );  --> boardarticle.xml의 id가 "in"인 tag와 연결됩니다.
	}

	//---*리스트
	@Override
	public List<Map<String, Object>> list( Map<String, Object> param ){
		return sqlSession.selectList( "boardarticle.list", param );
	}

	//---*one row
	@Override
	public Map<String, Object> one( Map<String, Object> param ){
		return (Map<String, Object>)sqlSession.selectOne( "boardarticle.one", param );
	}

	//---*업데이트
	@Override
	public int up( Map<String, Object> param ){
		return sqlSession.update( "boardarticle.up", param );
	}

}

 

별로 복잡하지 않죠? 처음엔 다 복잡하지?

그 이유는 Mybatis를 사용하기 때문에 쿼리가 mapper xml파일에 들어가 있기 때문이죠!

BoardarticleSvcImpl.in 에서 BoardarticleDaoImpl.in으로 처리가 넘어가는 것 뿐입니다.

그리고 다시 BoardarticleDaoImpl.in에서 Mapper 파일인 boardarticle.xml 의 id가 "in"인 태그를 찾아 가는 것입니다.

이제 마지막으로 Mapper파일 boardarticle.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="boardarticle">

	<insert id="in" parameterType="hashmap" useGeneratedKeys="true" keyProperty="seq" >
		INSERT INTO BOARDARTICLE
		(
			SEQ
			,TITLE
			,CONTENT
			,READCNT
			,COMMENTCNT
			,RECOMMENDCNT
			,GROUPNUM
			,LEVELNUM
			,STEPNUM
			,INIP
			,INDATE
		)values(
			#{ seq, jdbcType=NUMERIC }
			,#{ title, jdbcType=VARCHAR }
			,#{ content, jdbcType=VARCHAR }
			,#{ readcnt, jdbcType=NUMERIC }
			,#{ commentcnt, jdbcType=NUMERIC }
			,#{ recommendcnt, jdbcType=NUMERIC }
			,#{ groupnum, jdbcType=NUMERIC }
			,#{ levelnum, jdbcType=NUMERIC }
			,#{ stepnum, jdbcType=NUMERIC }
			,#{ inip, jdbcType=VARCHAR }
			,SYSDATE()
		)
	</insert>

</mapper>

 

id가 "in"인 것만 남겨놓은 파일입니다. 기본 insert Query입니다.

useGeneratedKeys을 "true"로 설정하고 keyProperty를 "seq"로 설정하게 되면

Mybatis에서 insert 후 primarykey인 seq를 전달 된 parameterType인 svcMap에 담아서 리턴해줍니다.

그래서 svcMap.get( "seq" )로 고유값을 가져올 수 있게 된 것이죠~

 

그렇다면 Spring에서는 boardarticle.xml을 어떻게 찾을 수 있을까요?

2강 application.properties 파일에서

mybatis.mapper-locations=classpath:com/soledot/**/*.xml 와 같이 설정했기 때문입니다.

classpath /com/soledot/ 하위에 있는 xml파일을 모두 읽어 놨기 때문에 가능합니다.

사실,

같은 Spring Framework나 SpringBoot라고 해도

구현 방식이 다양할 수 있습니다.

저도 최근에서 DAO class 대신 Mapper class를 만들어서 사용중입니다.

@Mapper를 사용할 수도 있습니다.

사용에 차이가 있는 것은 아니고... 설정에 차이일뿐입니다.

 

boardarticle.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="boardarticle">

	<select id="cnt" parameterType="hashmap" resultType="int">
		SELECT COUNT(*) FROM BOARDARTICLE
		<where>
			<if test="null != seq and '' != seq">AND SEQ = #{seq}</if>
			<if test="null != title and '' != title">AND TITLE = #{title}</if>
			<if test="null != content and '' != content">AND CONTENT = #{content}</if>
			<if test="null != readcnt and '' != readcnt">AND READCNT = #{readcnt}</if>
			<if test="null != commentcnt and '' != commentcnt">AND COMMENTCNT = #{commentcnt}</if>
			<if test="null != recommendcnt and '' != recommendcnt">AND RECOMMENDCNT = #{recommendcnt}</if>
			<if test="null != groupnum and '' != groupnum">AND GROUPNUM = #{groupnum}</if>
			<if test="null != levelnum and '' != levelnum">AND LEVELNUM = #{levelnum}</if>
			<if test="null != stepnum and '' != stepnum">AND STEPNUM = #{stepnum}</if>
			<if test="null != inip and '' != inip">AND INIP = #{inip}</if>
			<if test="null != indate and '' != indate">AND INDATE = #{indate}</if>
		</where>
	</select>

	<delete id="del" parameterType="hashmap">
		DELETE FROM BOARDARTICLE
		<where>
			<if test="null != seq and 0 lt seq">AND SEQ = #{seq}</if>
			<if test="null != title and '' != title">AND TITLE = #{title}</if>
			<if test="null != content and '' != content">AND CONTENT = #{content}</if>
			<if test="null != readcnt and '' != readcnt">AND READCNT = #{readcnt}</if>
			<if test="null != commentcnt and '' != commentcnt">AND COMMENTCNT = #{commentcnt}</if>
			<if test="null != recommendcnt and '' != recommendcnt">AND RECOMMENDCNT = #{recommendcnt}</if>
			<if test="null != groupnum and '' != groupnum">AND GROUPNUM = #{groupnum}</if>
			<if test="null != levelnum and '' != levelnum">AND LEVELNUM = #{levelnum}</if>
			<if test="null != stepnum and '' != stepnum">AND STEPNUM = #{stepnum}</if>
			<if test="null != inip and '' != inip">AND INIP = #{inip}</if>
			<if test="null != indate and '' != indate">AND INDATE = #{indate}</if>
		</where>
	</delete>

	<select id="edit" parameterType="hashmap" resultType="hashmap" >
		SELECT * FROM BOARDARTICLE
		<where>
			<if test="null != seq and 0 lt seq">AND SEQ = #{seq}</if>
			<if test="null != title and '' != title">AND TITLE = #{title}</if>
			<if test="null != content and '' != content">AND CONTENT = #{content}</if>
			<if test="null != readcnt and '' != readcnt">AND READCNT = #{readcnt}</if>
			<if test="null != commentcnt and '' != commentcnt">AND COMMENTCNT = #{commentcnt}</if>
			<if test="null != recommendcnt and '' != recommendcnt">AND RECOMMENDCNT = #{recommendcnt}</if>
			<if test="null != groupnum and '' != groupnum">AND GROUPNUM = #{groupnum}</if>
			<if test="null != levelnum and '' != levelnum">AND LEVELNUM = #{levelnum}</if>
			<if test="null != stepnum and '' != stepnum">AND STEPNUM = #{stepnum}</if>
			<if test="null != inip and '' != inip">AND INIP = #{inip}</if>
			<if test="null != indate and '' != indate">AND INDATE = #{indate}</if>
		</where>
	</select>

	<insert id="in" parameterType="hashmap" useGeneratedKeys="true" keyProperty="seq" >
		INSERT INTO BOARDARTICLE
		(
			SEQ
			,TITLE
			,CONTENT
			,READCNT
			,COMMENTCNT
			,RECOMMENDCNT
			,GROUPNUM
			,LEVELNUM
			,STEPNUM
			,INIP
			,INDATE
		)values(
			#{ seq, jdbcType=NUMERIC }
			,#{ title, jdbcType=VARCHAR }
			,#{ content, jdbcType=VARCHAR }
			,#{ readcnt, jdbcType=NUMERIC }
			,#{ commentcnt, jdbcType=NUMERIC }
			,#{ recommendcnt, jdbcType=NUMERIC }
			,#{ groupnum, jdbcType=NUMERIC }
			,#{ levelnum, jdbcType=NUMERIC }
			,#{ stepnum, jdbcType=NUMERIC }
			,#{ inip, jdbcType=VARCHAR }
			,SYSDATE()
		)
	</insert>

	<select id="list" parameterType="hashmap" resultType="hashmap">
		SELECT * FROM BOARDARTICLE
		<where>
			<if test="null != seq and '' != seq">AND SEQ = #{seq}</if>
			<if test="null != title and '' != title">AND TITLE = #{title}</if>
			<if test="null != content and '' != content">AND CONTENT = #{content}</if>
			<if test="null != readcnt and '' != readcnt">AND READCNT = #{readcnt}</if>
			<if test="null != commentcnt and '' != commentcnt">AND COMMENTCNT = #{commentcnt}</if>
			<if test="null != recommendcnt and '' != recommendcnt">AND RECOMMENDCNT = #{recommendcnt}</if>
			<if test="null != groupnum and '' != groupnum">AND GROUPNUM = #{groupnum}</if>
			<if test="null != levelnum and '' != levelnum">AND LEVELNUM = #{levelnum}</if>
			<if test="null != stepnum and '' != stepnum">AND STEPNUM = #{stepnum}</if>
			<if test="null != inip and '' != inip">AND INIP = #{inip}</if>
			<if test="null != indate and '' != indate">AND INDATE = #{indate}</if>
		</where>
		<if test="null != orderby and '' != orderby">ORDER BY ${orderby}</if>
		<if test="null != endrow and 0 lt endrow">LIMIT #{startrow}, #{endrow}</if>
	</select>

	<select id="one" parameterType="hashmap" resultType="hashmap">
		SELECT * FROM BOARDARTICLE
		<where>
			<if test="null != seq and '' != seq">AND SEQ = #{seq}</if>
			<if test="null != title and '' != title">AND TITLE = #{title}</if>
			<if test="null != content and '' != content">AND CONTENT = #{content}</if>
			<if test="null != readcnt and '' != readcnt">AND READCNT = #{readcnt}</if>
			<if test="null != commentcnt and '' != commentcnt">AND COMMENTCNT = #{commentcnt}</if>
			<if test="null != recommendcnt and '' != recommendcnt">AND RECOMMENDCNT = #{recommendcnt}</if>
			<if test="null != groupnum and '' != groupnum">AND GROUPNUM = #{groupnum}</if>
			<if test="null != levelnum and '' != levelnum">AND LEVELNUM = #{levelnum}</if>
			<if test="null != stepnum and '' != stepnum">AND STEPNUM = #{stepnum}</if>
			<if test="null != inip and '' != inip">AND INIP = #{inip}</if>
			<if test="null != indate and '' != indate">AND INDATE = #{indate}</if>
		</where>
	</select>

	<update id="up" parameterType="hashmap"  >
		UPDATE BOARDARTICLE
		<set>
			<if test="null != title">TITLE=#{title},</if>
			<if test="null != content">CONTENT=#{content},</if>
			<if test="null != readcnt">READCNT=#{readcnt},</if>
			<if test="null != commentcnt">COMMENTCNT=#{commentcnt},</if>
			<if test="null != recommendcnt">RECOMMENDCNT=#{recommendcnt},</if>
			<if test="null != groupnum">GROUPNUM=#{groupnum},</if>
			<if test="null != levelnum">LEVELNUM=#{levelnum},</if>
			<if test="null != stepnum">STEPNUM=#{stepnum},</if>
			<if test="null != inip">INIP=#{inip},</if>
		</set>
		<where>
			<if test="null != seq">AND SEQ=#{seq}</if>
		</where>
	</update>

</mapper>

 

다음에는 파일업로드 처리를 해볼까 합니다.

파일업로드와 답글 처리까지 되어야 보통 일반적인 학습 과정일까요?

여튼 얼마전에 오타 댓글 달아주신 분이 계셔서 오타는 수정했습니다.

궁금한 내용은 댓글 달아주시면 아는데로 답변 드리겠습니다.

그런데... 댓글 알림 기능을 안만들어놔서 언제 확인할지 모릅니다.

근데... 이거 따라하시면서 잘 돌아가는지 모르겠네...

 

공유하기:

스프링부트 카테고리 글 :

0 Comments

Comment