📌 IoC 제어 역전
프로그램 제어 흐름의 주도권을 외부로 넘겨주는 것
📌 DI 의존성 주입
객체가 필요한 종속성을 외부에서 주입해주는 것을 “의존성 주입”
=> IOC는 느슨한 결합을 만들기 위한 틀이고, 그 과정으로 DI를 사용한다.
메모 생성(Create), 메모 조회(Read), 메모 수정(Update), 메모 삭제(Delete)를 구현한다.

entity pacakge -> Memo.java
package com.sparta.memo.entity;
import com.sparta.memo.dto.MemoRequestDto;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
public class Memo {
private Long id;
private String username;
private String contents;
public Memo(MemoRequestDto requestDto) {
this.username = requestDto.getUsername();
this.contents = requestDto.getContents();
}
}
dto pacakge -> MemoRequestDto.java
package com.sparta.memo.dto;
import lombok.Getter;
@Getter
public class MemoRequestDto {
private String username;
private String contents;
}
dto pacakge -> MemoResponseDto.java
package com.sparta.memo.dto;
import com.sparta.memo.entity.Memo;
import lombok.Getter;
@Getter
public class MemoResponseDto {
private Long id;
private String username;
private String contents;
public MemoResponseDto(Memo memo) {
this.id = memo.getId();
this.username = memo.getUsername();
this.contents = memo.getContents();
}
}
controller package -> MemoController.java
package com.sparta.memo.controller;
import com.sparta.memo.dto.MemoRequestDto;
import com.sparta.memo.dto.MemoResponseDto;
import com.sparta.memo.entity.Memo;
import org.springframework.web.bind.annotation.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api")
public class MemoController {
private final Map<Long, Memo> memoList= new HashMap<>();
@PostMapping("/memos")
public MemoResponseDto create(@RequestBody MemoRequestDto requestDto) {
// RequestDto -> Entity
Memo memo = new Memo(requestDto);
// Memo Max ID Check
Long maxId = memoList.size() > 0 ? Collections.max(memoList.keySet()) + 1 : 1;
memo.setId(maxId);
// DB 저장
memoList.put(memo.getId(), memo);
// Entity -> ResponseDto
MemoResponseDto memoResponseDto = new MemoResponseDto(memo);
return memoResponseDto;
}
@GetMapping("/memos")
public List<MemoResponseDto> getMemos() {
// Map To List
List<MemoResponseDto> responseList = memoList.values().stream()
.map(MemoResponseDto::new).toList();
return responseList;
}
}
controller package -> MemoController.java
@PutMapping("/memos/{id}")
public Long updateMemo(@PathVariable Long id, @RequestBody MemoRequestDto requestDto) {
// 해당 메모가 DB에 존재하는지 확인
if(memoList.containsKey(id)) {
// 해당 메모 가져오기
Memo memo = memoList.get(id);
// memo 수정
memo.update(requestDto);
return memo.getId();
} else {
throw new IllegalArgumentException("선택한 메모는 존재하지 않습니다.");
}
}
@DeleteMapping("/memos/{id}")
public Long deleteMemo(@PathVariable Long id) {
// 해당 메모가 DB에 존재하는지 확인
if(memoList.containsKey(id)) {
// 해당 메모 삭제
memoList.remove(id);
return id;
} else {
throw new IllegalArgumentException("선택한 메모는 존재하지 않습니다.");
}
}
application.properties 설정
spring.application.name=memo
spring.datasource.url=jdbc:mysql://localhost:3306/memo
spring.datasource.username=root
spring.datasource.password={비밀번호}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
controller package -> MemoController.java
package com.sparta.memo.controller;
import com.sparta.memo.dto.MemoRequestDto;
import com.sparta.memo.dto.MemoResponseDto;
import com.sparta.memo.entity.Memo;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.web.bind.annotation.*;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
@RestController
@RequestMapping("/api")
public class MemoController {
// JDBC DB 생성
private final JdbcTemplate jdbcTemplate;
// JDBC DB 초기화 <-final 이므로
public MemoController(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@PostMapping("/memos")
public MemoResponseDto createMemo(@RequestBody MemoRequestDto requestDto) {
// RequestDto -> Entity
Memo memo = new Memo(requestDto);
// DB 저장
KeyHolder keyHolder = new GeneratedKeyHolder(); // 기본 키를 반환받기 위한 객체
String sql = "INSERT INTO memo (username, contents) VALUES (?, ?)"; // 값은 동적이므로 ?, ?
jdbcTemplate.update( con -> {
PreparedStatement preparedStatement = con.prepareStatement(sql,
Statement.RETURN_GENERATED_KEYS);
preparedStatement.setString(1, memo.getUsername());
preparedStatement.setString(2, memo.getContents());
return preparedStatement;
},
keyHolder);
// DB Insert 후 받아온 기본키 확인
Long id = keyHolder.getKey().longValue();
memo.setId(id);
// Entity -> ResponseDto
MemoResponseDto memoResponseDto = new MemoResponseDto(memo);
return memoResponseDto;
}
@GetMapping("/memos")
public List<MemoResponseDto> getMemos() {
// DB 조회
String sql = "SELECT * FROM memo";
return jdbcTemplate.query(sql, new RowMapper<MemoResponseDto>() {
@Override
public MemoResponseDto mapRow(ResultSet rs, int rowNum) throws SQLException {
// SQL 의 결과로 받아온 Memo 데이터들을 MemoResponseDto 타입으로 변환해줄 메서드
Long id = rs.getLong("id");
String username = rs.getString("username");
String contents = rs.getString("contents");
return new MemoResponseDto(id, username, contents);
}
});
}
@PutMapping("/memos/{id}")
public Long updateMemo(@PathVariable Long id, @RequestBody MemoRequestDto requestDto) {
// 해당 메모가 DB에 존재하는지 확인
Memo memo = findById(id);
if(memo != null) {
// memo 내용 수정
String sql = "UPDATE memo SET username = ?, contents = ? WHERE id = ?";
jdbcTemplate.update(sql, requestDto.getUsername(), requestDto.getContents(), id);
return id;
} else {
throw new IllegalArgumentException("선택한 메모는 존재하지 않습니다.");
}
}
@DeleteMapping("/memos/{id}")
public Long deleteMemo(@PathVariable Long id) {
// 해당 메모가 DB에 존재하는지 확인
Memo memo = findById(id);
if(memo != null) {
// memo 삭제
String sql = "DELETE FROM memo WHERE id = ?";
jdbcTemplate.update(sql, id);
return id;
} else {
throw new IllegalArgumentException("선택한 메모는 존재하지 않습니다.");
}
}
private Memo findById(Long id) {
// DB 조회
String sql = "SELECT * FROM memo WHERE id = ?";
return jdbcTemplate.query(sql, resultSet -> {
if(resultSet.next()) {
Memo memo = new Memo();
memo.setUsername(resultSet.getString("username"));
memo.setContents(resultSet.getString("contents"));
return memo;
} else {
return null;
}
}, id);
}
}
dto pacakge -> MemoResponseDto.java
package com.sparta.memo.dto;
import com.sparta.memo.entity.Memo;
import lombok.Getter;
@Getter
public class MemoResponseDto {
private Long id;
private String username;
private String contents;
public MemoResponseDto(Memo memo) {
this.id = memo.getId();
this.username = memo.getUsername();
this.contents = memo.getContents();
}
public MemoResponseDto(Long id, String username, String contents) {
this.id = id;
this.username = username;
this.contents = contents;
}
}
숙제
1번 수강생을 관리하는 MANAGER 테이블을 만들어보세요.
/* 1 번 답안 */
CREATE TABLE if not exists MANAGER
(
id bigint primary key comment '관리자 ID',
name varchar(2) not null comment '관리자 이름',
student_code varchar(100) not null comment '수강생 코드',
CONSTRAINT manager_fk_student_code FOREIGN KEY(student_code) REFERENCES STUDENT(student_code)
);
/* 2 번 답안 */
ALTER TABLE MANAGER MODIFY COLUMN id bigint AUTO_INCREMENT;
3번 INSERT를 이용하여 수강생 s1, s2, s3, s4, s5를 관리하는 managerA와 s6, s7, s8, s9를 관리하는 managerB를 추가하세요.
/* 3 번 답안 */
INSERT INTO MANAGER (name, student_code) VALUES('mA', 's1');
INSERT INTO MANAGER (name, student_code) VALUES('mA', 's2');
INSERT INTO MANAGER (name, student_code) VALUES('mA', 's3');
INSERT INTO MANAGER (name, student_code) VALUES('mA', 's4');
INSERT INTO MANAGER (name, student_code) VALUES('mA', 's5');
INSERT INTO MANAGER (name, student_code) VALUES('mB', 's6');
INSERT INTO MANAGER (name, student_code) VALUES('mB', 's7');
INSERT INTO MANAGER (name, student_code) VALUES('mB', 's8');
INSERT INTO MANAGER (name, student_code) VALUES('mB', 's9');
/* 4번 답안 */
/* mA 관리를 받는 학생들의 이름과, 주차별 시험점수 */
/* DISTINCT: 중복 값 삭제 */
SELECT DISTINCT
s.name AS student_name,
e.exam_seq AS exam_sequence,
e.score AS exam_score
FROM
MANAGER m
JOIN
STUDENT s ON m.student_code = s.student_code
JOIN
Exam e ON s.student_code = e.student_code
WHERE
m.name = 'mA';
5번. STUDENT 테이블에서 s1 수강생을 삭제했을 때 EXAM에 있는 s1수강생의 시험성적과 MANAGER의 managerA가 관리하는 수강생 목록에 자동으로 삭제될 수 있도록 하세요.
/* 5번 답안 */
ALTER TABLE EXAM DROP FOREIGN KEY exam_fk_student_code;
ALTER TABLE EXAM ADD CONSTRAINT exam_fk_student_code
FOREIGN KEY (student_code) REFERENCES STUDENT(student_code)
ON DELETE CASCADE;
ALTER TABLE MANAGER DROP FOREIGN KEY manager_fk_student_code;
ALTER TABLE MANAGER ADD CONSTRAINT manager_fk_student_code
FOREIGN KEY (student_code) REFERENCES STUDENT(student_code)
ON DELETE CASCADE;