[B -2-8] CRUD 게시판 목록 구현

2019. 9. 29. 17:19Project B (SPMS)/Project B 파트2

반응형

게시판 라우팅 테이블 설계

작업 URL 메소드 파라미터 입력화면 필요 URL 이동
전체 목록 /board/list GET × × ×
등록 처리 /board/register POST 전체 항목
상세 조회 /board/read GET 글번호 × ×
수정 처리 /board/remove POST 전체 항목
삭제 처리 /board/modify POST 글번호

 

게시판 구현을 하기에 앞서서 게시판 라우팅 설계 작성을 하는게 좋다.


테이블 및 더미 데이터 생성

 

...더보기
-- 게시판 시퀀스 생성
create sequence SEQ_BOARD;

-- 게시판 테이블 생성
create table TBL_BOARD (
  BNO number(10,0),
  TITLE varchar2(200) not null,
  content varchar2(2000) not null,
  WRITER varchar2(50) not null,
  REGDATE date default SYSDATE, 
  UPDATEDATE date default SYSDATE
);

-- 게시판 테이블 제약조건 추가
alter table TBL_BOARD add constraint PK_BOARD 
primary key (BNO);

-- 더미 데이터의 추가
insert into TBL_BOARD(BNO, TITLE, CONTENT, WRITER)
values(SEQ_BOARD.nextval, '첫번째 테스트 제목', '첫번째 테스트 내용', 'guest1');
insert into TBL_BOARD(BNO, TITLE, CONTENT, WRITER)
values(SEQ_BOARD.nextval, '두번째 테스트 제목', '두번째 테스트 내용', 'guest2');
insert into TBL_BOARD(BNO, TITLE, CONTENT, WRITER)
values(SEQ_BOARD.nextval, '세번째 테스트 제목', '세번째 테스트 내용', 'guest3');
insert into TBL_BOARD(BNO, TITLE, CONTENT, WRITER)
values(SEQ_BOARD.nextval, '네번째 테스트 제목', '네번째 테스트 내용', 'guest4');
insert into TBL_BOARD(BNO, TITLE, CONTENT, WRITER)
values(SEQ_BOARD.nextval, '다섯번째 테스트 제목', '다섯번째 테스트 내용', 'guest5');

-- 데이터 조작 적용
commit;

-- 테이블 확인
select * from TBL_BOARD;

 

게시물은 각 게시물마다 고유의 번호가 필요하므로 시퀀스를 이용해서 게시판 번호 항목에 데이터를 삽입한다.

게시판 테이블 데이터

 


게시판 VO 작성 

src/main/java

com.spms.domain

BoardVO.java

 

...더보기
package com.spms.domain;

import java.util.Date;

import lombok.Data;

@Data
public class BoardVO {
	private Long bno;
	private String title;
	private String content;
	private String writer;
	private Date regdate;
	private Date updateDate; 
}

@Data

@Getter, @Setter, @RequiredArgsConstructor, @ToString, @EqualsAndHashCode한꺼번에 설정해주는 매우 유용한 어노테이션이다.


게시판 컨트롤러 작성 : 목록

 

src/main/java

com.spms.controller

BoardController.java

 

...더보기
package com.spms.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.spms.service.BoardService;

import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j;

@Controller
@Log4j
@RequestMapping("/board/*")
@AllArgsConstructor
public class BoardController {

	private BoardService boardService;
	
	@GetMapping("/list")
	public void list(Model model) {
		log.info("list");
		boardService.getList().forEach(board -> log.info(board));
		model.addAttribute("list",boardService.getList());
	}
}

 

@Controller

컨트롤러 담당 스프링 빈으로 인식

 

@RequestMapping("/board/*")

BoardController 가 속한 패키지는

ServletConfig.java 파일에 @ComponentScan(basePackages = {"com.spms.controller"}) 로 정의되어 있으므로 별도의 설정이 필요하지 않다.

 

@AllArgsConstructor

BoardService에 대한 의존객체가 필요하므로 생성자로 자동으로 주입하도록 한다.

private BoardService boardService;

(*) 만약 생성자를 만들지 않을 경우 @Setter(onMethod_ = { @Autowired }) 를 이용해서 처리

 

@GetMapping("/list")

게시물 목록 매핑


게시판 서비스 인터페이스 작성 : 목록

 

src/main/java

com.spms.service

BoardService.java 인터페이스

 

...더보기
package com.spms.service;

import java.util.List;

import com.spms.domain.BoardVO;

public interface BoardService {
	public List<BoardVO> getList();
}

 


게시판 서비스 인터페이스 구현 작성 : 목록

 

src/main/java

com.spms.service

BoardServiceImpl.java

 

...더보기
package com.spms.service;

import java.util.List;

import org.springframework.stereotype.Service;

import com.spms.domain.BoardVO;
import com.spms.mapper.BoardMapper;

import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j;

@Log4j
@Service
@AllArgsConstructor
public class BoardServiceImpl implements BoardService {
	
	private BoardMapper boardMapper;
	
	@Override
	public List<BoardVO> getList() {
		// TODO Auto-generated method stub
		log.info("getList....");
		return boardMapper.getList();
	}

}

 

@Service

서비스 (비즈니스 영역) 담당 스프링 빈으로 인식.

 

@AllArgsConstructor

모든 파라미터에 대해 자동 생성주입

BoardMapper에 대한 의존객체가 필요하므로 생성자로 자동으로 주입하도록 한다.

private BoardMapper boardMapper;

(*) 만약 생성자를 만들지 않을 경우 @Setter(onMethod_ = { @Autowired }) 를 이용해서 처리

 


루트 환경설정에 서비스 등록

 

src/main/java

com.spms.config

RootConfig.java

 

...더보기
package com.spms.config;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

@Configuration
@ComponentScan(basePackages= {"com.spms.service"})
@MapperScan(basePackages = {"com.spms.mapper"})
public class RootConfig {
	
	@Bean
	public DataSource dataSource() {
		HikariConfig hikariConfig = new HikariConfig();
		hikariConfig.setDriverClassName("net.sf.log4jdbc.sql.jdbcapi.DriverSpy");
		hikariConfig.setJdbcUrl("jdbc:log4jdbc:oracle:thin:@호스트주소:1521:본인의SID");
		hikariConfig.setUsername("아이디");
		hikariConfig.setPassword("패스워드");
		HikariDataSource dataSource = new HikariDataSource(hikariConfig);
		return dataSource;
	}
	
	@Bean
	public SqlSessionFactory sqlSessionFactory() throws Exception {
		SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
		sqlSessionFactory.setDataSource(dataSource());
		return sqlSessionFactory.getObject();
	}
}

@ComponentScan(basePackages= {"com.spms.service"})

해당 패키지를 자동으로 스캔해서 스프링 빈으로 등록


게시판 매퍼 인터페이스 작성 : 목록

 

src/main/java

com.spms.mapper

BoardMapper.java 인터페이스

 

...더보기
package com.spms.mapper;

import java.util.List;
import com.spms.domain.BoardVO;

public interface BoardMapper {
	public List<BoardVO> getList();
}

게시판 매퍼 인터페이스 구현 작성 (SQL XML) : 목록

 

src/main/resources

com

spms

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.spms.mapper.BoardMapper">

	<select id="getList" resultType="com.spms.domain.BoardVO">
	<![CDATA[
		select * 
		from TBL_BOARD
		where BNO > 0 
	]]>
	</select>

</mapper>

XML CDATA 

XML에서 부등호를 사용하기 위해 사용된다.

 

where BNO > 0

게시판 테이블 생성 시 BNO항목 PK 제약조건을 추가했었는데,  PK 제약조건생성하면, 자동으로 유니크 인덱스(UNIQUE INDEX)생성된다.

유니크 인덱스를 가지고 테이블 검색 시 인덱스를 타게 하기위해 사용된다.

 


게시판 목록 유닛테스트 작성

 

src/test/java

com.spms.controller

BoardControllerTests.java

 

...더보기
package com.spms.controller;


import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import lombok.Setter;
import lombok.extern.log4j.Log4j;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = {
com.spms.config.RootConfig.class,
com.spms.config.ServletConfig.class} )
@Log4j
public class BoardControllerTests {

	@Setter(onMethod_ = { @Autowired })
	private WebApplicationContext ctx;

	private MockMvc mockMvc;

	@Before
	public void setup() {
		this.mockMvc = MockMvcBuilders.webAppContextSetup(ctx).build();
	}
	
	@Test
	public void testList() throws Exception {

		log.info(
			mockMvc.perform(MockMvcRequestBuilders.get("/board/list")
		).andReturn().getModelAndView().getModelMap());
	}
}

 


게시판 목록 유닛테스트 결과

 

...더보기
|----|------------|------------|-------|----------------------|----------------------|
|bno |title       |content     |writer |regdate               |updatedate            |
|----|------------|------------|-------|----------------------|----------------------|
|2   |첫번째 테스트 제목  |첫번째 테스트 내용  |guest1 |2019-09-29 13:46:56.0 |2019-09-29 13:46:56.0 |
|3   |두번째 테스트 제목  |두번째 테스트 내용  |guest2 |2019-09-29 13:46:56.0 |2019-09-29 13:46:56.0 |
|4   |세번째 테스트 제목  |세번째 테스트 내용  |guest3 |2019-09-29 13:46:56.0 |2019-09-29 13:46:56.0 |
|5   |네번째 테스트 제목  |네번째 테스트 내용  |guest4 |2019-09-29 13:46:56.0 |2019-09-29 13:46:56.0 |
|6   |다섯번째 테스트 제목 |다섯번째 테스트 내용 |guest5 |2019-09-29 13:46:56.0 |2019-09-29 13:46:56.0 |
|9   |테스트 새글 제목   |테스트 새글 내용   |user00 |2019-09-30 09:33:54.0 |2019-09-30 09:33:54.0 |
|10  |테스트 새글 제목   |테스트 새글 내용   |user00 |2019-09-30 09:46:44.0 |2019-09-30 09:46:44.0 |
|----|------------|------------|-------|----------------------|----------------------|

 

 

 

 

반응형