BoardContoller 코드 리뷰
package com.multi.erp.board;
import java.util.List;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.multi.erp.member.MemberDTO;
@Controller
public class BoardController {
BoardService service;
public BoardController() {
}
@Autowired
public BoardController(BoardService service) {
super();
this.service = service;
}
@GetMapping("/board/write")
public String writePage() {
return "board/writepage";//view
}
@PostMapping("/board/write")
public String write(BoardDTO board) {
System.out.println(board);
service.insert(board);
return "redirect:/board/list.do?category=all";//컨트롤러 요청재지정
}
@RequestMapping("/board/list.do")
public ModelAndView list(String category) {
System.out.println(category+"=======");
ModelAndView mav =new ModelAndView("board/list");
List<BoardDTO> boardlist = service.findByCategory(category);
mav.addObject("category",category);
mav.addObject("boardlist",boardlist);
System.out.println(boardlist);
return mav;//view
}
@RequestMapping("/board/search.do")
public ModelAndView search(String tag,String search) {
ModelAndView mav =new ModelAndView("board/list");
List<BoardDTO> boardlist = service.search(tag,search);
mav.addObject("boardlist",boardlist);
System.out.println(boardlist);
return mav;
}
@RequestMapping("/board/read.do")
public String read(String board_no,String state,Model model) {
BoardDTO board = service.getBoardInfo(board_no);
String view="";
if(state.equals("READ")) {
view= "board/read";
}else {
view = "board/update";
}
model.addAttribute("board", board);
return view;
}
@RequestMapping("/board/delete.do")
public String read(String board_no,HttpSession session) {
MemberDTO user = (MemberDTO) session.getAttribute("user");
String view="";
if(user==null) {//로그인 하지 않은 상태
view = "redirect:/emp/login.do";
}else {//로그인상태
int result = service.delete(board_no);
view = "redirect:/board/list.do?category=all";
}
return view;
}
@PostMapping("/board/update.do")
public String update(BoardDTO board) {
System.out.println(board);
service.update(board);
return "redirect:/board/list.do";//컨트롤러 요청재지정
}
}
BoardService : 게시판 관련 비즈니스 로직을 수행하는 서비스를위한 인터페이스 .
@Autowired 어노테이션을 통해 Spring이 자동으로 이서비스를 BoardContorller에 주입한다.
-------------------------------------------------------------------------------------------------------------------------------------------
writePage() : "board/write" GET요청을 처리하며, 게시판 글 작성페이지를 반환한다.
-------------------------------------------------------------------------------------------------------------------------------------------
write(BoardDTO board) : "/board/write" POST 요청을 처리, 게시판에 새로운 글을 추가한다.
-------------------------------------------------------------------------------------------------------------------------------------------
list(String category): "/board/list.do" 요청을 처리하며, 특정 카테고리의 모든 게시글을 가져와서 보여준다.
-------------------------------------------------------------------------------------------------------------------------------------------
search(String tag, String search): "/board/saech.do" 요청을 처리, 사용자가 입력한 태그와 검색어를 기반으로 게시글 을 검색
------------------------------------------------------------------------------------------------------------------------------------------
read(String board_no, String state,Model model): "/board/read.do"요청을 처리, 특정 게시글의 내용을 보여주거나
수정 페이지를 보여준다.
------------------------------------------------------------------------------------------------------------------------------------------
read(Stirng board_no, HttpSession session): "/board/delete.do"요청을 처리하며, 특정 게시글을 삭제. 로그인된 사 용자만 이 기능을 사용할수 있다.
------------------------------------------------------------------------------------------------------------------------------------------
update(BoardDTO board): "/board/update.do" POST 요청을 처리, 게시글을 수정한다.
------------------------------------------------------------------------------------------------------------------------------------------
전체 요약: 이 클래스는 게시판의 기본적인 CRUD(Create,Read,Update,Delete)작업을 처리하는 메소드를 제공한다.
Spring MVC 패턴에서 컨트롤러는 사용자의 요청을 받아 해당 요청에 대한 비즈니스 로직을 수행하고 결과 를 뷰에게 전달하는 역활을 한다.
--------------------------------------------------------------------------------------------------------------------------------------------
BoardDAO 코드 리뷰(주석으로 정리)
package com.multi.erp.board;
import java.util.List;
import org.springframework.stereotype.Repository;
//mybatis의 SqlSession을 이용해서 작업
public interface BoardDAO {
//게시글등록 - db에 처리
int insert(BoardDTO board);
//게시글목록보기 - db에 처리
List<BoardDTO> boardList();
//게시글상세조회 - db에 처리
BoardDTO read(String board_no);
//게시글수정 - db에 처리
int update(BoardDTO board);
//게시글삭제 - db에 처리
int delete(String board_no);
//제목으로 검색
List<BoardDTO> search(String data);
//제목,작성자, 본문, 작성일별로 검색
List<BoardDTO> search(String tag,String data);
//category 별로 검색
List<BoardDTO> findByCategory(String category);
//=================첨부파일을 조회하기 위한 기능=========================
//첨부파일을 저장하기 위한 메소드
//int insertFile(List<BoardFileDTO> boardfiledtolist);
//게시글을 상세보기한 경우 보여질 업로드한 파일의 목록 조회
//List<BoardFileDTO> getFileList(String boardno);
//BoardFileDTO getFile(BoardFileDTO inputdata);
}
BoardDAOImpl 코드 리뷰
package com.multi.erp.board;
import java.util.HashMap;
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;
@Repository
public class BoardDAOImpl implements BoardDAO {
//Mybatis의 핵심클래스를 이용해서 sql문을 실행
SqlSession sqlSessionTemplate;
public BoardDAOImpl() {
}
@Autowired
public BoardDAOImpl(SqlSession sqlSessionTemplate) {
super();
this.sqlSessionTemplate = sqlSessionTemplate;
}
@Override
public int insert(BoardDTO board) {
//SqlSession의 insert메소드는 insert SQL명령문을 실행하기 위해 제공되는 메소드
//insert(statement,파라미터객체)
//statement가 매퍼에 정의한 sql문을 구분하는 id명 - 네임스페이스명,id명
//파라미터객체 -사용자가 입력한 값이 저장되어 있는 DTO
return sqlSessionTemplate.insert("com.multi.erp.board.insert", board);
}
@Override
public List<BoardDTO> boardList() {
// TODO Auto-generated method stub
return sqlSessionTemplate.selectList("com.multi.erp.board.selectall");
}
@Override
public BoardDTO read(String board_no) {
// TODO Auto-generated method stub
return sqlSessionTemplate.selectOne("com.multi.erp.board.read", board_no);
}
@Override
public int update(BoardDTO board) {
// TODO Auto-generated method stub
return sqlSessionTemplate.update("com.multi.erp.board.update", board);
}
@Override
public int delete(String board_no) {
// TODO Auto-generated method stub
return sqlSessionTemplate.delete("com.multi.erp.board.delete", board_no);
}
@Override
public List<BoardDTO> search(String data) {
// TODO Auto-generated method stub
return sqlSessionTemplate.selectList("com.multi.erp.board.search",data);
}
@Override
public List<BoardDTO> search(String tag, String data) {
List<BoardDTO> list = null;
System.out.println(tag+",========================"+data);
Map<String,String> map = new HashMap<String, String>();
map.put("tag", tag);//key에 정의한 값을 mybatis에서 매핑
map.put("data", data);
list = sqlSessionTemplate.selectList("com.multi.erp.board.dynamicsearch",map);
return list;
}
@Override
public List<BoardDTO> findByCategory(String category) {
System.out.println(category);
List<BoardDTO> list = sqlSessionTemplate.selectList("com.multi.erp.board.categorySearch",category);
System.out.println("====dao===="+list.size());
return list;
}
}
이 코드는 Spring Framework와 MyBatis를 이용하여 데이터베이스에 접근하는 DAO(Data Access Object) 클래스를 구현하고 "BoardDAOImpl"은 "BoardDAO" 인터페이스를 구현하며 게시판 관련 데이터베이스 작업을 담당.
- SqlSession sqlSessionTemplate: MyBatis의 핵심 클래스인 SqlSession을 사용하여 SQL문을 실행한다 "@Autowired"어노테이션을 통해 Spring이 자동으로 인스턴스를 주입한다.
- insert(BoardDTO board): 게시글을 넣고 MyBatis의 "insert"메소드를 사용하여 SQL문을 실행하고 이 메소드는 삽입된 행의 수를 반환한다.
- boardList(): 모든 게시글을 조회한다. Mybatis의 "selectList" 메소드를 사용하여 SQL문을 실행한다.
- read(String board_no) : 특정 게시글을 조회한다 MyBatis의 "selectOne" 메소드를 사용하여 SQL문을 실행한다.
- update(BoardDTO board) : 게시글을 업데이트한다. MyBatis의 "update" 메소드를 사용하여 SQL문을 실행하며 업데이트된 행의 수를 반환한다.
- delete(String data) : 데이터를 이용하여 게시글을 검색한다. MyBatis의 "delete" 메소드를 사용하여 SQL문을 실행한다.
- search(String data) : 데이터를 이용하여 게시글을 검색한다. MyBatis의 "selectList" 메소드를 사용하여 SQL문을 실행한다.
- search(String tag,String data) : 태그와 데이터를 이용하여 게시글을 동적 검색한다 MyBatis의 "selectList" 메소드를 사용하여 SQL문을 실행한다.
- findBycategory(String category) : 카테고리를 이용하여 게시글을 검색한다. MyBatis의 "selectList" 메소드를 사용하여 SQL문을 실행한다.
최종 요약: MyBatis를 이용하여 SQL문을 실행한다.
BoardDTO 코드 리뷰 (설명생략)
package com.multi.erp.board;
import java.sql.Date;
import java.util.List;
import org.springframework.web.multipart.MultipartFile;
public class BoardDTO {
String board_no;
String id;
Date write_date;
String title;
String content;
String category;
public BoardDTO() {
}
public BoardDTO(String board_no, String id, Date write_date, String title, String content, String category) {
super();
this.board_no = board_no;
this.id = id;
this.write_date = write_date;
this.title = title;
this.content = content;
this.category = category;
}
@Override
public String toString() {
return "BoardDTO [board_no=" + board_no + ", id=" + id + ", write_date=" + write_date + ", title=" + title
+ ", content=" + content + ", category=" + category +"]";
}
public String getBoard_no() {
return board_no;
}
public void setBoard_no(String board_no) {
this.board_no = board_no;
}
public String getId() {
System.out.println("getId()");
return id;
}
public void setId(String id) {
System.out.println("setId()");
this.id = id;
}
public Date getWrite_date() {
return write_date;
}
public void setWrite_date(Date write_date) {
this.write_date = write_date;
}
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 getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
}
BoardService 코드 리뷰(주석설명)
package com.multi.erp.board;
import java.util.List;
//dao의 메소드를 호출
public interface BoardService {
//게시글등록 - tbboard테이블과 board_file테이블에 저장
//int insert(BoardDTO board,List<BoardFileDTO> boardfiledtolist);
int insert(BoardDTO board);
//게시글목록보기
List<BoardDTO> boardList();
//게시글상세조회
BoardDTO getBoardInfo(String board_no);
//게시글수정
int update(BoardDTO board);
//게시글삭제
int delete(String board_no);
//제목으로 검색
List<BoardDTO> search(String data);
//제목,작성자, 본문, 작성일별로 검색
List<BoardDTO> search(String tag,String data);
//category별로 검색하기
List<BoardDTO> findByCategory(String category);
//게시글을 상세보기한 경우 보여질 업로드한 파일의 목록 조회
//List<BoardFileDTO> getFileList(String boardno);
//BoardFileDTO getFile(BoardFileDTO inputdata);
}
BoardServiceImpl 코드 리뷰
package com.multi.erp.board;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
//BoardDAO의 메소드를 호출
//=> 컨트롤러에서 받은 데이터를 가공해서 DAO로 넘기거나 DAO에서 받은 데이터를 가공해서 컨트롤러로 넘기는 작업
//=> 비지니스로직
//=> 트랜잭션처리
@Service
public class BoardServiceimpl implements BoardService {
BoardDAO dao;
public BoardServiceimpl() {
}
@Autowired
public BoardServiceimpl(BoardDAO dao) {
super();
this.dao = dao;
}
@Override
public int insert(BoardDTO board) {
return dao.insert(board);
}
@Override
public List<BoardDTO> boardList() {
// TODO Auto-generated method stub
return dao.boardList();
}
@Override
public BoardDTO getBoardInfo(String board_no) {
// TODO Auto-generated method stub
return dao.read(board_no);
}
@Override
public int update(BoardDTO board) {
// TODO Auto-generated method stub
return dao.update(board);
}
@Override
public int delete(String board_no) {
// TODO Auto-generated method stub
return dao.delete(board_no);
}
@Override
public List<BoardDTO> search(String data) {
// TODO Auto-generated method stub
return dao.search(data);
}
@Override
public List<BoardDTO> search(String tag, String data) {
// TODO Auto-generated method stub
return dao.search(tag, data);
}
//조건을 판단해서 dao의 적절한 메소드를 호출하기- 비지니스로직
@Override
public List<BoardDTO> findByCategory(String category) {
List<BoardDTO> list = null;
if(category!=null) {
if(category.equals("all")) {
list =dao.boardList();
}else {
list = dao.findByCategory(category);
}
}
return list;
}
}
"BoardServiceImpl" 은 "BoardService" 인터페이스를 구현하며 컨트롤러와 DAO 사이의 중간 계층인 서비스 계층을 담당한다.
BoardDAO dao : BoardDAO 인터페이스를 참조하는 변수며 이변수를 통해 DAO의 메소드를 호출한다.
"@Autowired" 어노테이션을 통해 Spring이 자동으로 인스턴스를 주입한다.
insert(BoardDTO board) : 게시글을 삽입하는 메소드이다 DAO의 "insert" 메소드를 호출한다.
boardList() : 모든 게시글을 조회하는 메소드이다 DAO의 boardList메소드를 호출한다.
getBoardInfo(String board_no) : 특정 게시글을 조회하는 메소드다. DAO의 "read" 메소드를 호출한다.
update(BoardDTO board) : 게시글을 업데이트하는 메소드다 DAO의 "update" 메소드를 호출한다.
delete(String data) : 데이터를 이용하여 게시글으 르검색하는 메소드다 DAO의 "delete" 메소드를 호출한다.
search(String data) : 데이터를 이용하여 게시글을 검색하는 메소드다 DAO의 "search" 메소드를 호출한다.
search(String tag, String data) : 태그와 데이터를 이용하여 개시글을 검색하는 메소드다 DAO의 "search"메소드를 호출한다.
findByCategory(String category) : 카테고리를 이용하여 게시글을 검색하는 메소드다 "all" 카테고리일 경우 모든 게시글을,
그렇지 않을 경우 특정 카테고리의 게시글을 조회한다.
최종 요약 : 이 클래스는 비즈니스 로직을 수행하는 메소드를 제공한다. 비즈니스 로직이란 사용자의 요청을 처리하는 로직 (예 : 데이터검증,계산 등)을 말한다 . 이 클래스는 DAO의 메소드를 호출하여 이런 로직을 수행하며 이를 통해 컨트롤러와 DAO 사이의 중간 계층 역활을 한다 . 이 계층은 필요에 따라 트랜잭션 처리등의 역활도 수행 가능하다.
-번외-(트랜잭션)
트랜잭션(Transaction)은 데이터베이스의 상태를 변화시키기 위해 수행하는 작업의 단위를 말합니다. 일반적으로 하나의 트랜잭션은 여러 개의 데이터베이스 연산으로 구성될 수 있으며, 이들 연산은 모두 성공적으로 수행되거나 (Commit), 하나라도 실패하면 모두 취소되어야 (Rollback) 합니다.
예를 들어, 은행 계좌 이체를 생각해보면, 한 계좌에서 다른 계좌로 돈을 옮기는 것은 두 개의 연산으로 이루어집니다. 하나는 한 계좌에서 돈을 빼는 것이고, 다른 하나는 다른 계좌에 돈을 더하는 것입니다. 이 두 연산은 하나의 트랜잭션으로 묶여야 합니다. 만약 두 번째 연산에서 문제가 발생한다면, 첫 번째 연산이 롤백되어 돈이 빠져나간 계좌에 다시 돈이 돌아가야 합니다.
트랜잭션은 ACID 속성을 만족해야 합니다.
원자성(Atomicity): 트랜잭션 내의 모든 연산은 모두 성공하거나 모두 실패해야 합니다.
일관성(Consistency): 트랜잭션이 성공적으로 수행되면 항상 일관성 있는 상태를 유지해야 합니다.
고립성(Isolation): 각 트랜잭션은 다른 트랜잭션의 연산에 영향을 받아서는 안 됩니다.
지속성(Durability): 성공적으로 수행된 트랜잭션은 영구적으로 반영되어야 합니다.
mapper: board.xml코드 리뷰
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- #{}으로 변수를 연결하면 PreparedStatement의 ?와 연결 -->
<mapper namespace="com.multi.erp.board">
<insert id="insert" parameterType="board">
insert into tbboard
values(null,#{id},sysdate(),#{title},#{content},#{category})
</insert>
<select id="selectall" resultType="board">
select * from tbboard
</select>
<select id="categorySearch" parameterType="String" resultType="board">
select * from tbboard where category=#{category}
</select>
<select id="search" resultType="board" parameterType="String">
select * from tbboard where title like concat('%', #{title},'%')
</select>
<select id="read" resultType="board" parameterType="String">
select * from tbboard where board_no = #{board_no}
</select>
<delete id="delete" parameterType="String">
DELETE FROM tbboard WHERE board_no = #{board_no}
</delete>
<update id="update" parameterType="board">
update tbboard
set title=#{title}, content=#{content}, category=#{category}
where board_no = #{board_no}
</update>
<!-- where절이 만들어지지 않는 상황이면 where절을 추가하지 않는다. -->
<select id="dynamicsearch" resultType="board" parameterType="Map">
select * from tbboard
<where>
<if test="tag=='title' and data!=''">
title like concat('%',#{data},'%')
</if>
<if test="tag=='id' and data!=''">
id like concat('%',#{data},'%')
</if>
<if test="tag=='content' and data!=''">
content like concat('%',#{data},'%')
</if>
<if test="tag=='write_date' and data!=''">
<![CDATA[
write_date <= #{data}
]]>
</if>
</where>
</select>
</mapper>
이 XML 파일은 Mybatis 프레임워크에서 사용하는 매퍼 파일이다 Mybatis는 java와 데이터베이스 사이의
퍼시스턴스(persistence)계층에서 사용되는 프레임워크로 SQL쿼리를 XML 파일로 분리하여 관리된다.
여기서 매퍼 파일은 SQL 쿼리와 java 객체를 매핑해주는 역활을 합니다.
"<mapper>" 태그 :
매퍼 파일의 시작과 끝을 나타내는 태그이다 "namespace" 속성은 이 매퍼가 어떤 DAO클래스에 속하는지를 나타낸다.
"<insert>" 태그 :
데이터를 데이터베이스에 삽입하는 SQL쿼리를 정의한다 "id"속성은 이 쿼리를 DAO에서 참조할 때 사용하는 이름이다.
"parameterType"은 쿼리에 전달될 파라미터의 타입을 나타낸다.
"<select>"태그 :
데이터를 데이터베이스에서 선택하는 SQL 쿼리를 정의한다.
"resultType"은 쿼리의 결과를 받을 객체의 타입을 나타낸다
"<delete>"태그 : 데이터베이스에서 데이터를 삭제하는 SQL 쿼리를 정의한다.
"<update>"태그 : 데이터베이스에서 데이터를 업데이트하는 SQL쿼리를 정의한다.
"<select id="dynamicsearach">" 태그 : 여러조건에 따라 동적으로 SQL 쿼리를 생성한다 "<where>" 태그 안에 "<if>" 태그를 사용하여 조건에 따라 다른 SQL 쿼리를 생성할 수 있다. "CDATA" 섹션은 문자 그대로의 데이터를 나타내며 이경우에는 특수문자 (< , > , "," ,<= 등)가 있는 SQL 쿼리를 안전하게 처리하기 위해 사용된다.
각 태그에서 "#{ }" 구문은 PreparedStatement의 파라미터를 참조한다 이는 SQL injection 공격을 방지하기 위한 안전한 방법이며 이 구문안에 들어가는 이름은 java 객체의 필드 이름과 일치해야 한다.
'코드리뷰' 카테고리의 다른 글
업로드 (0) | 2023.05.15 |
---|---|
MyBatis, Spring (com.multi.erp.member) (0) | 2023.05.13 |
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!