Spring/컨셉

스프링(Spring) 테이블 조인(Join) 예제

minwoohi 2018. 9. 7. 10:23

스프링 테이블 조인 예제. 게시글 작성할 때 작성자에 대한 정보를 갖기 위해 조인이 필요하다.
게시글 객체인 BoardVO에 작성자 객체인 UserVO를 멤버변수로 만들어 사용한다.


package com.blog.naver.user.vo;

import org.hibernate.validator.constraints.NotEmpty;

public class UserVO { // userId
	
	@NotEmpty(message="userId 입력하세요")
	private String userId;
	@NotEmpty(message="userName 입력하세요")
	private String userName;
	@NotEmpty(message="userPassword 입력하세요")
	private String userPassword;
	private String joinDate;
	public String getUserId() {
		return userId;
	}
	public void setUserId(String userId) {
		this.userId = userId;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getUserPassword() {
		return userPassword;
	}
	public void setUserPassword(String userPassword) {
		this.userPassword = userPassword;
	}
	public String getJoinDate() {
		return joinDate;
	}
	public void setJoinDate(String joinDate) {
		this.joinDate = joinDate;
	}
	
	
	
}

UserVO 객체.

package com.blog.naver.board.vo;

import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.web.multipart.MultipartFile;

import com.blog.naver.user.vo.UserVO;

public class BoardVO {
	
	private int boardId;
	private MultipartFile file;
	@NotEmpty(message="제목을 입력해야 합니다.")
	@Length(min=2, message="제목은 최소 2자 이상")
	private String subject;
	@NotEmpty(message="내용을 입력해야 합니다")
	private String content;
	private String writer;
	private int likeCount;
	private String writeDate;
	private String ip;
	private String post;
	private String realFileName;
	
	private UserVO userVO;
	
	public String getPost() {
		return post;
	}

	public void setPost(String post) {
		this.post = post;
	}

	public int getBoardId() {
		return boardId;
	}
	
	public void setBoardId(int boardId) {
		this.boardId = boardId;
	}
	public String getSubject() {
		return subject;
	}
	public void setSubject(String subject) {
		this.subject = subject;
	}
	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 int getLikeCount() {
		return likeCount;
	}
	public void setLikeCount(int likeCount) {
		this.likeCount = likeCount;
	}
	public String getWriteDate() {
		return writeDate;
	}
	public void setWriteDate(String writeDate) {
		this.writeDate = writeDate;
	}
	public String getIp() {
		return ip;
	}
	public void setIp(String ip) {
		this.ip = ip;
	}
	public MultipartFile getFile() {
		return file;
	}
	public void setFile(MultipartFile file) {
		this.file = file;
	}

	public UserVO getUserVO() { // Spring VO에서는 Null check 할 필요 없음~
		return userVO;
	}

	public void setUserVO(UserVO userVO) {
		this.userVO = userVO;
	}

	public String getRealFileName() {
		return realFileName;
	}

	public void setRealFileName(String realFileName) {
		this.realFileName = realFileName;
	}
	
	
}

BoardVO 객체. UserVO 객체를 멤버변수로 갖고 있다. 서블릿과 달리 스프링에서는 getter에서 객체 값 null인지 확인할 필요도 없어진다.
boardDaoSql.xml 파일에 조인 쿼리문을 작성한다. 조인된 커맨드 객체를 리턴하기 위해서는 resultMap을 통해 쿼리문과 VO 객체의 데이터를 맵핑한다.
resultMap - type : 객체 타입
resultMap - id : resultMap 명
id : PK 멤버변수 지정. 
id - column : DB 칼럼명
id - property : 커맨드 객체 멤버변수 명
result : PK 이외의 멤버변수 지정
column, property는 id와 같은 방법으로 사용한다.
association : 연관된 데이터를 맵핑시킨다.
javaType : 조인될 객체 타입
property : 커맨드 객체에서의 변수명

이후 select 쿼리의 속성에 작성한 resultMap의 id를 입력하면 그 결과값을 받아올 수 있다.
쿼리문은 서블릿과 동일해 생략



<resultMap type="BoardVO" id="boardMap">
		<id column="BOARD_ID" property="boardId" />
		<result column="SUBJECT" property="subject" />
		<result column="CONTENT" property="content" />
		<result column="WRITER" property="writer" />
		<result column="WRITE_DATE" property="writeDate" />
		<result column="LIKE_COUNT" property="likeCount" />
		<result column="IP" property="ip" />
		<result column="PST" property="post" />
		<result column="RL_FL_NM" property="realFileName" />
		
		<!-- 1 : 다 관계의 경우 데이터 매핑시켜준다. 
			association => 1 : 1 관계 
			collection => 1 : 다 관계 (한명의 유저가 작성한 글 목록)
			일반 컬럼과 pk 구분 가능 pk 칼럼에게는 result 아닌 id 사용
		-->
		<association javaType="UserVO" property="userVO">
			<id column="USR_ID" property="userId"/>
			<result column="USR_NM" property="userName"/>
			<result column="JOIN_DT" property="joinDate"/>
		</association>
	</resultMap>
	
	<select id="selectOneArticle"
			 parameterType="_int"
			 resultMap="boardMap">
		SELECT	/*[BoardDao][selectOneArticle]*/
				B.BOARD_ID
				, B.SUBJECT
				, B.CONTENT
				, B.WRITER
				, B.WRITE_DATE
				, B.LIKE_COUNT
				, B.IP
				, B.PST
				, B.RL_FL_NM
				, U.USR_ID
				, U.USR_NM
				, U.JOIN_DT
		FROM	BOARD B
				, USRS U
		WHERE	B.WRITER = U.USR_ID
		AND		BOARD_ID = #{boardId} /*-- board 객체의 boardId 아니고 매개변수명이다~ */
	</select>
@RequestMapping("/board/detail/{id}")
	public ModelAndView ViewDetailPage(@PathVariable int id, HttpSession session){
		ModelAndView view = new ModelAndView();
		
		UserVO user = (UserVO) session.getAttribute("_USER_");
		
		if(user != null){
			BoardVO board = boardService.getOneBoard(id);
			
			view.setViewName("board/detail");
			view.addObject("board", board);
			
		} else {
			view.setViewName("user/signIn");
		}
		return view;
	}

boardId에 해당하는 게시글 객체(BoardVO)를 가져온다. UserVO 객체가 조인되어 있어 jsp에서 UserVO 객체 정보에도 접근해 확인해 보도록 한다.



<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c"  uri="http://java.sun.com/jsp/jstl/core"%>

<!DOCTYPE html >
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>/board/detail.jsp</title>
</head>
<body>

	<h1>boardId : ${board.boardId }</h1>
	<h2>subject : ${board.subject }</h2>
	<c:if test="${not empty board.post }">
		<a href="<c:url value="/board/download/${board.boardId }"/>">${board.post }</a>
	</c:if>
	<h2>content : ${board.content }</h2>
	<h2>writer : ${board.writer }</h2>
	<h2>likeCount : ${board.likeCount }</h2>
	<h2>userVO.userId : ${board.userVO.userId }</h2>
	<h2>userVO.userName : ${board.userVO.userName }</h2>
	<h2>userVO.joinDate : ${board.userVO.joinDate }</h2>
	<a href="<c:url value="board/delete/${board.boardId }" />">글 삭제~</a>

</body>
</html>

board/detail.jsp

다음과 같이 조인된 결과가 잘 나온다.

프로젝트 파일은 https://github.com/minwoohi/spring_board 을 참조