2022-03-30(์ˆ˜)

์„ธ์…˜์„ ์‚ฌ์šฉํ•˜๋Š” request handler
ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ณด๋‚ธ ์„ธ์…˜ID๋กœ ์ด์ „์— ์ƒ์„ฑํ•œ ์„ธ์…˜ ๊ฐ์ฒด๋ฅผ ์ฐพ๋Š”๋‹ค.

๋ฌดํšจํ•œ ์„ธ์…˜์ด๋ฉด ์ƒˆ๋กœ ์„ธ์…˜ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด์„œ ๋„˜๊ฒจ์ค€๋‹ค

์„œ๋ฒ„์—์„œ ์ƒ์„ฑํ•œ ์„ธ์…˜ID

์„ธ์…˜ID๋Š” ์›น๋ธŒ๋ผ์šฐ์ €์—์„œ ์ƒ์„ฑํ•˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ ์„œ๋ฒ„์—์„œ ์ƒ์„ฑํ•˜๋Š” ๊ฑฐ

์„ธ์…˜์„ ์ƒˆ๋กœ ๋งŒ๋“  ๊ฒŒ ์•„๋‹ˆ๋ฉด ์‘๋‹ตํ•  ๋•Œ ์„ธ์…˜ID๋ฅผ ๋ฆฌํ„ดํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค

์ƒˆ๋กœ ๋งŒ๋“ค์—ˆ์„ ๋•Œ๋งŒ ์‘๋‹ต ํ—ค๋”์— ํฌํ•จ๋œ๋‹ค

์ด๋ฆ„(๊ฐœ๋…)
๊ตฌ์กฐ๋„
ํ๋ฆ„(๊ณผ์ •)
์•„์ง ๊ตฌ์ฒด์ ์œผ๋กœ ๋จธ๋ฆฌ๋กœ ๊ทธ๋ ค์ง€์ง€ ์•Š์œผ๋‹ˆ๊นŒ ๋จธ๋ฆฌ์— 20~30%๋งŒ ๋‚จ์Œ
์„ธ์…˜ID๋Š” ์›น๋ธŒ๋ผ์šฐ์ €์—์„œ ์ƒ์„ฑํ•˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ ์„œ๋ฒ„์—์„œ ์ƒ์„ฑํ•˜๋Š” ๊ฑฐ

    fetch("/member/signup", { // ๋น„๋™๊ธฐ ๋ฐฉ์‹์œผ๋กœ ์„œ๋ฒ„์— ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค.
        method: "POST",
        body: new URLSearchParams(fd)
      })

http://localhost:8080/member/form.html

// MemberController

  @RequestMapping("/member/signin")
  public Object signin(String email, String password) {
    return memberService.get(email, password);
  }
public interface MemberService {

  int add(Member member);

  Member get(String email, String password);
}

  @Override
  public Member get(String email, String password) {
    return memberDao.findByEmailAndPassword(email, password);
  }

@Param์„ ์‚ฌ์šฉํ•˜์—ฌ SQL Mapper์—์„œ ์‚ฌ์šฉํ•  ์ด๋ฆ„ ์ง€์ •
๋ณดํ†ต์€ ๊ฐ™๊ฒŒ ํ•œ๋‹ค

public interface MemberDao {

  int insert(Member member);

  Member findByEmailAndPassword(@Param("email") String email, @Param("password") String password);
  <select id="findByEmailAndPassword" resultMap="memberMap">
    select
      no,
      name,
      email
    from
      ml_member
    where
      email=#{email} and password=password(#{password})
  </select>

  <resultMap type="member" id="memberMap">
    <id column="no" property="no"/>
    <result column="name" property="name"/>
    <result column="email" property="email"/>
    <result column="regist_date" property="registDate"/>
  </resultMap>

http://localhost:8080/member/signin.html

http://localhost:8080/member/signin?email=user1@test.com&password=abc123

json์œผ๋กœ ๋ฐ”๊พธ๊ธฐ

    fetch("/member/signin", { // ๋น„๋™๊ธฐ ๋ฐฉ์‹์œผ๋กœ ์„œ๋ฒ„์— ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค.
        method: "POST",
        body: new URLSearchParams(fd)
      })
      .then(function(response) {
        return response.json();
      })
      .then(function(obj) {
        console.log(obj);
        window.alert("๋กœ๊ทธ์ธ ์„ฑ๊ณต");
      });
    fetch("/member/signin", { // ๋น„๋™๊ธฐ ๋ฐฉ์‹์œผ๋กœ ์„œ๋ฒ„์— ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค.
        method: "POST",
        body: new URLSearchParams(fd)
      })
      .then(function(response) {
        return response.json();
      })
      .then(function(obj) {
    	  if (obj == "") {
    		  window.alert("๋กœ๊ทธ์ธ ์‹คํŒจ!");
    	  } else {    		  
        window.alert(obj.name + "๋‹˜ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค!");
    	  }
      });
  @RequestMapping("/member/signin")
  public Object signin(String email, String password) {
    Member loginUser = memberService.get(email, password);
    if (loginUser == null) {
      return "";
    } else {      
      return loginUser;
    }
  }

json์„ ์ผ๋ฐ˜ ๋ฌธ์ž์—ด๋กœ ๋ณด๋‚ด๋ฉด ์•ˆ ๋˜๋„ค... null์„ ๋ณด๋‚ด๋„ ์•ˆ ๋˜๋„ค

  @RequestMapping("/member/signin")
  public Object signin(String email, String password) {
    Member loginUser = memberService.get(email, password);
    if (loginUser == null) {
      return "fail";
    } else {      
      return "success";
    }
  }
    fetch("/member/signin", { // ๋น„๋™๊ธฐ ๋ฐฉ์‹์œผ๋กœ ์„œ๋ฒ„์— ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค.
        method: "POST",
        body: new URLSearchParams(fd)
      })
      .then(function(response) {
        return response.text();
      })
      .then(function(text) {
    	  if (text == "success") {
    		  location.href = "../index.html";
    	  } else {    		  
    		  window.alert("๋กœ๊ทธ์ธ ์‹คํŒจ!");
    	  }
      });

๋กœ๊ทธ์ธ ์„ฑ๊ณตํ•˜๋ฉด index.html๋กœ ์˜ด

  @RequestMapping("/member/signin")
  public Object signin(String email, String password, HttpSession session) {
    Member loginUser = memberService.get(email, password);
    if (loginUser == null) {
      return "fail";
    }

    // ๋กœ๊ทธ์ธ์ด ์„ฑ๊ณตํ•˜๋ฉด,
    // ๋‹ค๋ฅธ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ๋•Œ ๋กœ๊ทธ์ธ ํšŒ์›์˜ ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ธ์…˜์— ๋ณด๊ด€ํ•œ๋‹ค.
    session.setAttribute("loginUser", loginUser);

    return "success";
  }

DAO ๊ตฌํ˜„์ฒด๊ฐ€ ์‚ฌ์šฉํ•  SQL Mapper ํŒŒ์ผ์˜ ์œ„์น˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค์˜ ํŒจํ‚ค์ง€ ๊ฒฝ๋กœ ๋ฐ ์ด๋ฆ„๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•œ๋‹ค.

SQL Mapper ํŒŒ์ผ ์ด๋ฆ„์ด๋ž‘ ์ธํ„ฐํŽ˜์ด์Šค ์ด๋ฆ„ํ•˜๊ณ  ๋˜‘๊ฐ™์•„์•ผ ํ•จ (MemberDao.xml)

http://localhost:8080/member/signin.html

<form name="form1">
์ด๋ฉ”์ผ: <input name="email" type="email"><br>
์•”ํ˜ธ: <input name="password" type="password"><br>
<div>
  <button id="x-add-btn">๋กœ๊ทธ์ธ</button>
  <button id="x-cancel-btn" type="button">์ทจ์†Œ</button>
</div>
<div>
  <a href="form.html">ํšŒ์›๊ฐ€์ž…</a>
</div>
</form>
  @RequestMapping("/member/signup")
  public Object signup(Member member) {
    if (memberService.add(member) == 1) {
      return "success";
    } else {
      return "fail";
    }
  }
// form.html

    fetch("/member/signup", { // ๋น„๋™๊ธฐ ๋ฐฉ์‹์œผ๋กœ ์„œ๋ฒ„์— ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค.
        method: "POST",
        body: new URLSearchParams(fd)
      })
      .then(function(response) {
        return response.text();
      })
      .then(function(text) {
    	  if (text == "success") {
    		  location.href = "signin.html";
    	  } else {
          window.alert("ํšŒ์›๊ฐ€์ž… ์‹คํŒจ!");
    	  }
      });
    return false;
  };

  document.querySelector("#x-cancel-btn").onclick = function() {
    window.location.href = "../index.html";
  };

์ƒ๋‹จ ๋ฉ”๋‰ด๋ฐ”๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

// index.html

  <style>
    #header {
      background-color: navy;
      color: white;
      height: 50px;
      display: flex;
      align-items: center;
    }
</style>
</head>
<body>
<div id="header">
  MyList
  <button id="login-btn" type="button">๋กœ๊ทธ์ธ</button>
  <button id="logout-btn" type="button">๋กœ๊ทธ์•„์›ƒ</button>
</div>
package com.eomcs.mylist.controller;

import lombok.Data;

@Data
public class ResultMap {
  final String status;
  final Object data;
}

final ๋ถ™์ด๋ฉด ์ƒ์„ฑ์ž

package com.eomcs.mylist.controller;

import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;

@Data
@NoArgsConstructor(force = true) // ๊ธฐ๋ณธ ์ƒ์„ฑ์ž๋ฅผ ๋ฌด์กฐ๊ฑด ๋งŒ๋“ค๊ฒŒ ํ•œ๋‹ค.
@RequiredArgsConstructor // final์ด ๋ถ™์€ ํ•„๋“œ์˜ ๊ฐ’์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๋Š” ์ƒ์„ฑ์ž๋ฅผ ๋งŒ๋“ค๊ฒŒ ํ•œ๋‹ค.
public class ResultMap {
  final String status;
  final Object data;
}
  @RequestMapping("/member/getLoginUser")
  public Object getLoginUser(HttpSession session) {
    Object data = session.getAttribute("loginUser");
    if (data != null) {
      return new ResultMap("success", data);
    } else {
      return new ResultMap("fail", "๋กœ๊ทธ์ธ ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.");
    }
  }

8๋‹จ๊ณ„ - ๋กœ๊ทธ์ธ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์กฐํšŒํ•œ๋‹ค.
โ€ข controller.ResultMap ํด๋ž˜์Šค ์ถ”๊ฐ€
JSON ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฆฌํ„ดํ•  ๋•Œ ์‚ฌ์šฉํ•  ํด๋ž˜์Šค
์ž‘์—… ์„ฑ๊ณต ์œ ๋ฌด์™€ ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•œ๋‹ค.

โ€ข MemberController ํด๋ž˜์Šค ๋ณ€๊ฒฝ
getLoginUser() ๋ฉ”์„œ๋“œ ์ถ”๊ฐ€

final, ์• ๋…ธํ…Œ์ด์…˜ ์ง€์šฐ๊ธฐ

package com.eomcs.mylist.controller;

import lombok.Data;

@Data
public class ResultMap {
  String status;
  Object data;
}

lombok setter return this ๊ฒ€์ƒ‰

์„ธํ„ฐ ๊ฒŒํ„ฐ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์ด ํ•„๋“œ ์ด๋ฆ„๊ณผ ๊ฐ™์•„
์„ธํ„ฐ์˜ ๋ฆฌํ„ด ํƒ€์ž…๋„ ResultMap

์ ‘๋‘์–ด(get/set)๋ฅผ ๋ถ™์ด๋Š” ๊ฒฝ์šฐ๋„ ์žˆ๊ณ  ์—†๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์Œ

@Accessors(fluent = true) ํ•˜๋ฉด ํ•„๋“œ ์ด๋ฆ„๊ณผ ๊ฐ™๊ฒŒ ๋งŒ๋“ค์–ด์ง„๋‹ค

์„ธํ„ฐ๋ฅผ ํ†ตํ•ด์„œ๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ

package com.eomcs.mylist.controller;

import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(fluent = true)
public class ResultMap {
  private String status;
  private Object data;
}

ํ•œ ๋ˆˆ์— ์•Œ์•„๋ณด๊ธฐ๊ฐ€ ์‰ฝ๋‹ค. ๊ทธ๋ž˜์„œ ์ด ๋ฐฉ๋ฒ•์„ ์“ฐ๋Š” ๊ฑฐ

  @RequestMapping("/member/getLoginUser")
  public Object getLoginUser(HttpSession session) {
    Object member = session.getAttribute("loginUser");
    if (member != null) {
      return new ResultMap().status("success").data(member);
    } else {
      return new ResultMap().status("fail").data("๋กœ๊ทธ์ธ ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.");
    }
  }

์—๋Ÿฌ ๋‚จ

json ์ถฉ๋Œ ์ผ์–ด๋‚จ
get, set์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š”
json ๋ฐ์ดํ„ฐ๋กœ ๋ฐ”๊พธ

@Accessors(chain = true) ๋กœ ๋ณ€๊ฒฝํ•˜๊ธฐ

  @RequestMapping("/member/getLoginUser")
  public Object getLoginUser(HttpSession session) {
    Object member = session.getAttribute("loginUser");
    if (member != null) {
      return new ResultMap()
          .setStatus("success")
          .setData(member);
    } else {
      return new ResultMap()
          .setStatus("fail")
          .setData("๋กœ๊ทธ์ธ ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.");
    }
  }

success ์ž…๋ ฅํ•˜๋‹ค ๋ณด๋ฉด ์˜คํƒ€ ๋‚  ์ˆ˜๋„ ์žˆ์Œ
์˜คํƒ€ ๋ฐฉ์ง€
์ƒ์ˆ˜๋กœ ์ •์˜ํ•ด๋†“๊ธฐ

package com.eomcs.mylist.controller;

import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
public class ResultMap {
  public static final String SUCCESS = "success";
  public static final String FAIL = "fail";  
  private String status;
  private Object data;
}
  @RequestMapping("/member/getLoginUser")
  public Object getLoginUser(HttpSession session) {
    Object member = session.getAttribute("loginUser");
    if (member != null) {
      return new ResultMap()
          .setStatus(ResultMap.SUCCESS)
          .setData(member);
    } else {
      return new ResultMap()
          .setStatus(ResultMap.FAIL)
          .setData("๋กœ๊ทธ์ธ ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.");
    }
  }

์ƒ์ˆ˜ import ํ•˜๊ธฐ

  @RequestMapping("/member/getLoginUser")
  public Object getLoginUser(HttpSession session) {
    Object member = session.getAttribute("loginUser");
    if (member != null) {
      return new ResultMap()
          .setStatus(SUCCESS)
          .setData(member);
    } else {
      return new ResultMap()
          .setStatus(FAIL)
          .setData("๋กœ๊ทธ์ธ ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.");
    }
  }
<div id="header">
  <span id="app-title">MyList</span>
  <span id="user-name"></span>
  <button id="login-btn" type="button">๋กœ๊ทธ์ธ</button>
  <button id="logout-btn" type="button">๋กœ๊ทธ์•„์›ƒ</button>
</div>
<script type="text/javascript">
  fetch("/member/getLoginUser").then(function(response) {
	  return response.json();
  }).then(function(result) {
	  document.querySelector("#user-name").innerHTML = result.data.name;
  });
</script>

  var el = document.querySelectorAll(".login");
  for (var e of el) {
	  e.style.display = "none"
  }

  function css(selector, name, value) {
	  var el = document.querySelectorAll(selector);
	  for (var e of el) {
	    e.style[name] = value;
	  }
  }

jQuery ์‚ฌ์šฉํ•˜๋Š” ์ด์œ 
์ฝ”๋“œ๊ฐ€ ๊ฐ„๊ฒฐํ•ด์ง„๋‹ค.
๋ธŒ๋ผ์šฐ์ €์— ๋งž์ถฐ์„œ ํ•ด๋‹น๋˜๋Š” ๊ธฐ๋Šฅ์ด ๋™์ž‘ํ•˜๋„๋ก ์ฝ”๋”ฉ๋˜์–ด ์žˆ๋‹ค.
ํฌ๋กœ์Šค ๋ธŒ๋ผ์šฐ์ง• ์ง€์›

9๋‹จ๊ณ„ - ๋กœ๊ทธ์•„์›ƒ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•œ๋‹ค.

๋กœ๊ทธ์•„์›ƒ์€ Controller๋งŒ ๋ฐ”๊พธ๋ฉด ๋จ

  @RequestMapping("/member/signout")
  public Object signout(HttpSession session) {
    session.invalidate();
    return new ResultMap().setStatus("success");
  }
  document.querySelector("#logout-btn").onclick = function() {
	  fetch("/member/signout").then(function(response) {
		  location.href = "/index.html"
		});
  }

18.2 ์„ธ์…˜๊ณผ ์ฟ ํ‚ค์˜ ํ™œ์šฉ: ์„ธ์…˜ ํ™œ์šฉํ•˜๊ธฐ

๋กœ๊ทธ์ธ๊ณผ ์„ธ์…˜์„ ํ™œ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž๋ณ„๋กœ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌํ•˜๊ธฐ

alter table ml_board
  add column writer int not null,
  add constraint ml_board_fk foreign key (writer) references ml_member(no);

๊ธฐ์กด ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์œผ๋ฉด not null ์ปฌ๋Ÿผ์€ ๋‚˜์ค‘์— ์ถ”๊ฐ€ ๋ถˆ๊ฐ€

๋จผ์ € ๊ธฐ์กด ๋ฐ์ดํ„ฐ ๋‹ค ์ง€์šฐ๊ธฐ

delete from ml_board;

3๋‹จ๊ณ„์— ๊ฑฐ์ณ์„œ ํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ์Œ
null ํ—ˆ์šฉํ•˜๊ณ  ๊ฐ’ ๋„ฃ๊ณ  ๋‹ค์‹œ not null๋กœ ๋ฐ”๊พธ๋Š” ๊ฑด ๊ฐ€๋Šฅ

2๋‹จ๊ณ„ - ๊ฒŒ์‹œ๊ธ€์„ ๋‹ค๋ฃจ๋Š” ๋„๋ฉ”์ธ ํด๋ž˜์Šค์— ํšŒ์› ๋ฒˆํ˜ธ๋ฅผ ๋‹ด๋Š” ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

Board ํด๋ž˜์Šค ๋ณ€๊ฒฝํ•˜๊ธฐ

@Data
public class Board {
  int no;
  String title;
  String content;
  int viewCount;
  java.sql.Date createdDate;
  int writer;
}

๊ฒŒ์‹œ๊ธ€ ์ž…๋ ฅ ์‹œ ์ž‘์„ฑ์ž ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜๋„๋ก SQL Mapper ํŒŒ์ผ์„ ๋ณ€๊ฒฝํ•œ๋‹ค

๊ฒŒ์‹œ๊ธ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃฐ ๋•Œ ์ž‘์„ฑ์ž ๋ฒˆํ˜ธ๋„ ํ•จ๊ป˜ ๋‹ค๋ฃฌ๋‹ค

  @RequestMapping("/board/add")
  public Object add(Board board, HttpSession session) {
    Member member = (Member) session.getAttribute("loginUser");
    if (member == null) {
      return new ResultMap().setStatus(FAIL).setData("๋กœ๊ทธ์ธ ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.");
    }
    board.setWriter(member.getNo());
    boardService.add(board);
    return new ResultMap().setStatus(SUCCESS);
  }

์ž๊ธฐ๊ฐ€ ์“ด ๊ธ€๋งŒ ๊ฐ€๋Šฅ

and writer=#{writer}

  <update id="update" parameterType="Board">
    update ml_board set 
      title=#{title}, 
      content=#{content} 
    where
      board_no=#{no} and writer=#{writer}
  </update>

parameterType="board"๋กœ ๋ณ€๊ฒฝํ•˜๊ธฐ

  <delete id="delete" parameterType="board">
    delete from ml_board 
    where board_no=#{no} and writer=#{writer}
  </delete>

5๋‹จ๊ณ„ - ๊ฒŒ์‹œ๊ธ€ ์กฐํšŒํ•  ๋•Œ ๋กœ๊ทธ์ธ ์‚ฌ์šฉ์ž์˜ ์ด๋ฆ„์„ ํ•จ๊ป˜ ์กฐํšŒํ•œ๋‹ค.

<resultMap> ์— Member ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€

https://mybatis.org/mybatis-3/sqlmap-xml.html

<association> โ† 1:1 ๊ด€๊ณ„์˜ ํ…Œ์ด๋ธ”์„ join ํ•  ๋•Œ ์‚ฌ์šฉ

  <!-- ํ…Œ์ด๋ธ”์˜ ์ปฌ๋Ÿผ๊ณผ ๊ฐ์ฒด ํ•„๋“œ๋ฅผ ์—ฐ๊ฒฐํ•œ๋‹ค. -->
  <resultMap type="board" id="boardMap">
    <id column="board_no" property="no"/>
    <result column="title" property="title"/>
    <result column="content" property="content"/>
    <result column="created_date" property="createdDate"/>
    <result column="view_count" property="viewCount"/>
    
    <association property="writer" javaType="member">
      <id column="no" property="no"/>
      <result column="name" property="name"/> 
    </association>
  </resultMap>

โ†“ name ์ปฌ๋Ÿผ ๊ฐ’์€ member ๊ฐ์ฒด์˜ name ์ด๋ผ๋Š” ํ•„๋“œ์— ์ €์žฅํ•ด๋ผ

<result column="name" property="name"/>

์ €๋ฒˆ ์‹œ๊ฐ„์—๋Š” ContactDao.xml์—์„œ <collection>์„ ์จ์„œ ์—ฐ๋ฝ์ฒ˜ ํ…Œ์ด๋ธ”๊ณผ ์ „ํ™”๋ฒˆํ˜ธ ํ…Œ์ด๋ธ”์„ join ํ–ˆ์—ˆ๋‹ค
<collection> โ† 1:M ๊ด€๊ณ„์˜ ํ…Œ์ด๋ธ”์„ join ํ•  ๋•Œ ์‚ฌ์šฉ

findAll, findByNo SQL๋ฌธ ๋ณ€๊ฒฝ: ml_member ํ…Œ์ด๋ธ”๊ณผ ์กฐ์ธํ•œ๋‹ค.

  <select id="findAll" resultMap="boardMap">
    select 
      b.board_no,
      b.title,
      b.created_date,
      b.view_count,
      m.no,
      m.name
    from 
      ml_board b
      inner join ml_member m on (b.writer = m.no) 
    order by 
      b.board_no desc
  </select>

๊ทธ๋Œ€๋กœ ๋ณต์‚ฌํ•ด์„œ sql๋ฌธ์ด ์˜ฌ๋ฐ”๋ฅธ์ง€ ํ™•์ธํ•œ๋‹ค.

    select 
      b.board_no,
      b.title,
      b.created_date,
      b.view_count,
      m.no,
      m.name
    from 
      ml_board b
      inner join ml_member m on (b.writer = m.no)
    order by 
      b.board_no desc;

์ž˜ ๋‚˜์˜จ๋‹ค

๊ฒŒ์‹œ๊ธ€๊ณผ ์ž‘์„ฑ์ž

90-MyListํ”„๋กœ์ ํŠธ2 / 67 ํŽ˜์ด์ง€

๐Ÿ”น ํ…Œ์ด๋ธ” ๊ด€๊ณ„ (ER-Diagram)
ml_board
ml_member
ํ•œ ๋ช…์˜ ๋ฉค๋ฒ„๋Š” 0๊ฐœ ์ด์ƒ์˜ ๊ฒŒ์‹œ๊ธ€์„ ์“ธ ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ”น ์ž๋ฐ” ๊ฐ์ฒด (UML Class Diagram) (๊ฐ์ฒด ๊ด€๊ณ„)
Board ๊ฐ์ฒด
Member ํด๋ž˜์Šค
Board ๊ฐ์ฒด๋Š” writer๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ Member ๊ฐ์ฒด 1๊ฐœ๋ฅผ ํฌํ•จํ•œ๋‹ค.

Class Diagram์— ๋”ฐ๋ผ ์†Œ์Šค์ฝ”๋“œ๋ฅผ ํ‘œํ˜„ํ•œ ๊ฒŒ โ†“
Board ์•ˆ์— Member๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ๋‹ค

Board ์•ˆ์— Member๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ๋‹ค

  <select id="findByNo" resultMap="boardMap" parameterType="int">
    select 
      b.board_no,
      b.title,
      b.content,
      b.created_date,
      b.view_count,
      m.no,
      m.name
    from 
      ml_board b
      inner join ml_member m on (b.writer = m.no) 
    where 
      b.board_no=#{no}
  </select>

์ด์ œ writer๋Š” int๊ฐ€ ์•„๋‹˜. (Member๋กœ ๋ฐ”๊ฟจ์Œ)
Board ๊ฐ์ฒด ์•ˆ์— ๋“ค์–ด ์žˆ๋Š” writer ๊ฐ์ฒด์˜ no (writer.no)

writer โ†’ writer.no

<insert>, <update>, <delete> SQL๋ฌธ ๋ณ€๊ฒฝ: writer ํ•„๋“œ์˜ ํƒ€์ž…์ด int์—์„œ Member ๋ณ€๊ฒฝ๋œ ๊ฒƒ์„ ์ ์šฉํ•œ๋‹ค.

BoardController ํด๋ž˜์Šค ๋ณ€๊ฒฝ
add(), update(), delete() ๋ฉ”์„œ๋“œ ๋ณ€๊ฒฝ

๋ฒˆํ˜ธ๊ฐ€ ์•„๋‹ˆ๋ผ Member ๊ฐ์ฒด๋ฅผ ๋‹ด๋Š”๋‹ค

member.getNo() โ†’ member

localhost:8080/board/list

board ๊ฐ์ฒด ์•ˆ์— writer ๊ฐ์ฒด๊ฐ€ ๋“ค์–ด ์žˆ๋‹ค

http://localhost:8080/board/get?no=12

${board.writer} โ†’ ${board.writer.name}

board ๊ฐ์ฒด์— writer ๋ผ๋Š” ํ•„๋“œ๊ฐ€ Member ๊ฐ์ฒด์ด๋‹ค
writer ๊ฐ์ฒด์˜ name ํ•„๋“œ

ํŽ˜์ด์ง€ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํ„ดํ•  ๋•Œ ์˜ˆ์ „์ฒ˜๋Ÿผ ํ…์ŠคํŠธ๋กœ ๋ฆฌํ„ดํ•˜์ง€ ์•Š๊ณ 
ํ•ญ์ƒ ResultMap์— ๋‹ด์•„์„œ ์„ฑ๊ณต ์‹คํŒจ ์—ฌ๋ถ€๋ฅผ ๋ฆฌํ„ดํ•˜์ž

์ข‹์€ ์›นํŽ˜์ด์ง€ ์ฆ๊ฒจ์ฐพ๊ธฐ