🚩 Controller, BO, Repository/Mapper 호출
- Controller는 여러 개의 BO를 호출할 수 있다.
- BO는 여러 개의 BO를 호출할 수 있다.
- BO는 본인과 매핑된 Repository/Mapper만 호출할 수 있다.
- Controller <- BO <- Mapper 방향으로 호출될 수는 있지만, 역방향은 불가하다.
- BO1에서 BO2를 호출했다면, BO2에서 BO1을 호출할 수 없다.(상호 autowired 안됨, 한 방향으로만 가능)
🚩 MyBatis 주의할 점
- 오버로딩을 지원하지 않는다.
- insert, update, delete 시, 성공적으로 완료된 행의 수를 반환한다.
src
└── main
├── java
│ └── 베이스 패키지
│ └── ...
│ ├── bo
│ │ └── 도매인명BO.java
│ ├── domain
│ │ └── 도매인명.java
│ ├── mapper
│ │ └── 도매인명Mapper.java
│ └── Controller.java
├── resources
│ └── mappers
│ └── 도매인명Mapper.xml
└── webapp
└── WEB-INF
└── jsp
└── ...
├── 페이지명1.jsp
├── 페이지명2.jsp
└── ...
1) 주요 어노테이션
@Controller
(JSP 경로 리턴->HTML)/@RestController
(객체 리턴->JSON, String 리턴->HTML)@RequestMapping("공통 요청 URL")
@Autowired
@RequestMapping(path = "요청 URL", method = RequestMethod.GET)
/@GetMapping("요청 URL")
@RequestMapping(path = "요청 URL", method = RequestMethod.POST)
/@PostMapping
@RequestMapping("요청 URL")
: @RequestParam("요청 파라미터명")
@RequestParam(value = "요청 파라미터명", required = false, defaultValue = "기본값")
@ModelAttribute
@RequestMapping("/{변수명}")
)변수명
의 값을 받는 파라미터: @PathVariable("변수명")
2) 주의 사항
auto_increase
속성을 가진 필드는 자동 생성되므로 삽입하지 않는다.?⭐️key⭐️=1
<-> (Controller 내부 메소드의 파라미터) @RequestParam("⭐️key⭐️") int id123
org.springframework.ui.Model
에서 import 한다.${obj.key}
혹은 ${key}
로 가져온다.return "redirect:재요청 보낼 주소"
로 작성한다.@ResponseBody
작성 후 String을 반환한다. (해당 포스팅 참고)3) 권장 사항
1) 주요 어노테이션
@Service
@Autowired
2) 주의 사항
3) 권장 사항
1) 주요 어노테이션
@Repository
@Param("파라미터명")
2) 주의 사항
@Param("⭐️param-name⭐️") int id123
<-> (Mapper.xml) #{⭐️param-name⭐️}
3) 권장 사항
1) 주요 속성
2) 주의 사항 & 권장 사항
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
Ctrl + 클릭
으로 연결 상태를 확인한다.*
사용을 지양한다.#{}
혹은 ${}
사용 안함)<if test="imagePath != null">, `imagePath` = #{imagePath}</if>
auto_increase
속성이 있는 필드: 자동 생성되므로 쿼리문에 작성하지 않는다.createdAt
, updatedAt
: default current_timestamp
속성이 있어 기본값으로 자동 삽입되더라도, 관례적으로 쿼리문을 작성한다.updatedAt
: NOW()
로 업데이트 일시를 변경하는 쿼리문을 작성한다.1) 주의 사항
createdAt
, updatedAt
의 자료형인 Date는 java.util.Date
에서 import 한다.2) 권장 사항
src
└── main
├── java
│ └── com.example
│ └── lesson04
│ ├── bo
│ │ └── StudentBO.java
│ ├── domain
│ │ └── Student.java
│ ├── mapper
│ │ └── StudentMapper.java
│ └── Lesson04Ex02Controller.java
├── resources
│ └── mappers
│ └── StudentMapper.xml
└── webapp
└── WEB-INF
└── jsp
└── lesson04
├── addStudent.jsp
└── afterAddStudent.jsp
🚩 가독성을 위해 import 문은 제외했습니다.
1) Controller
// 🟢 Lesson04Ex02Controller.java
package com.example.lesson04;
@RequestMapping("/lesson04/ex02")
@Controller
public class Lesson04Ex02Controller {
@Autowired
private StudentBO studentBO;
// 학생 추가 화면
@GetMapping("/add-student-view")
public String addStudentView() {
return "lesson04/addStudent";
}
// 방금 가입된 학생 화면(학생 추가 완료 후 화면)
@PostMapping("/add-student")
public String addStudent(
@ModelAttribute Student student,
Model model) {
// DB insert
studentBO.addStudent(student);
// DB에서 방금 가입된 사용자 select
int id = student.getId();
Student latestStudent = studentBO.getStudentById(id);
// Model 객체에 담는다.(JSP에서 사용하도록)
model.addAttribute("student", latestStudent);
// JSP 경로 리턴
return "lesson04/afterAddStudent";
}
}
2) Service(= BO)
// 🟢 StudentBO.java
package com.example.lesson04.bo;
@Service
public class StudentBO {
@Autowired
private StudentMapper studentMapper;
public void addStudent(Student student) {
studentMapper.insertStudent(student);
}
public Student getStudentById(int id) {
return studentMapper.selectStudentById(id);
}
}
3) Repository(= DAO, Mapper)
// 🟣 StudentMapper.java
package com.example.lesson04.mapper;
@Repository
public interface StudentMapper {
public void insertStudent(Student student);
public Student selectStudentById(int id);
}
<!-- 🟤 StudentMapper.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.example.lesson04.mapper.StudentMapper">
<insert id="insertStudent" parameterType="com.example.lesson04.domain.Student" useGeneratedKeys="true" keyProperty="id">
INSERT INTO `new_student`
(
`name`
, `phoneNumber`
, `email`
, `dreamJob`
, `createdAt`
, `updatedAt`
)
VALUES
(
#{name}
, #{phoneNumber}
, #{email}
, #{dreamJob}
, NOW()
, NOW()
)
</insert>
<select id="selectStudentById" parameterType="int" resultType="com.example.lesson04.domain.Student">
SELECT
`id`
, `name`
, `phoneNumber`
, `email`
, `dreamJob`
, `createdAt`
, `updatedAt`
FROM
`new_student`
WHERE
`id` = #{id}
</select>
</mapper>
4) Domain(= Entity, Model)
// 🟢 Student.java
package com.example.lesson04.domain;
public class Student {
private int id;
private String name;
private String phoneNumber;
private String email;
private String dreamJob;
private Date createdAt;
private Date updatedAt;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getDreamJob() {
return dreamJob;
}
public void setDreamJob(String dreamJob) {
this.dreamJob = dreamJob;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
}
5) JSP
<%-- 🟡 addStudent.jsp --%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>학생 추가</title>
<!-- BootStrap -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct" crossorigin="anonymous"></script>
</head>
<body>
<div class="container">
<h1>회원가입</h1>
<form method="post" action="/lesson04/ex02/add-student">
<div class="form-group">
<label for="name">이름</label>
<input type="text" id="name" name="name" class="form-control col-4">
</div>
<div class="form-group">
<label for="phoneNumber">핸드폰 번호</label>
<input type="text" id="phoneNumber" name="phoneNumber" class="form-control col-4">
</div>
<div class="form-group">
<label for="email">이메일</label>
<input type="text" id="email" name="email" class="form-control col-4">
</div>
<div class="form-group">
<label for="dreamJob">장래희망</label>
<input type="text" id="dreamJob" name="dreamJob" class="form-control col-4">
</div>
<input type="submit" value="회원가입" class="btn btn-success">
</form>
</div>
</body>
</html>
<%-- 🟡 afterAddStudent.jsp --%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>방금 가입된 사용자 정보</title>
<!-- BootStrap -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct" crossorigin="anonymous"></script>
</head>
<body>
<div class="container">
<h1>방금 가입된 사용자 정보</h1>
<table class="table table-striped">
<tr>
<th>id</th>
<td>${student.id}</td>
</tr>
<tr>
<th>이름</th>
<td>${student.name}</td>
</tr>
<tr>
<th>핸드폰 번호</th>
<td>${student.phoneNumber}</td>
</tr>
<tr>
<th>이메일</th>
<td>${student.email}</td>
</tr>
<tr>
<th>장래희망</th>
<td>${student.dreamJob}</td>
</tr>
<tr>
<th>생성일</th>
<td>${student.createdAt}</td>
</tr>
<tr>
<th>수정일</th>
<td>${student.updatedAt}</td>
</tr>
</table>
</div>
</body>
</html>