Tiny Star

📌TIL [Today I Learn]

[TIL] 23년 6월 14일 수요일

청크 2023. 6. 14. 21:26

23년 6월 14일 수요일

오늘의 목표 : Spring 기초 1주차 완강 / 2주차 수강 시작하기

 

오늘 공부한 내용🤓

1]

어제 잘 되지 않았던 메모오류를 먼저 해결했다.

 

튜터님께 찾아가서 같이 디버깅을 해보면서 데이터를 보내는 곳에서 문제가 있다는 것을 알았고

다시 처음부터 차근차근 코드를 점검해봤는데 역시나 내 실수였다.

 

MemoResponseDto 생성자에서memo.get이 아닌 그냥 get만 넣었으니.. 당연히 안불러와지는 것...

심지어 id값은 memo.getId();의 형태로 불러와놓고 Username/contents 두개는 그냥 불러오는 큰 실수를 저질렀다.

 

그래서 재빨리 수정한 코드..!

    public MemoResponseDto(Memo memo) {
        this.id = memo.getId();
        this.username = memo.getUsername();
        this.contents = memo.getContents();
    }

오류 해결하고 메모장 update와 delete 기능구현까지 오류없이 진도를 나갈 수 있었다.

 

2]

Database / SQL

처음 메모장에서는 데이터베이스를 사용하지 않아서 Map으로 저장데이터를 받아왔다. Map에 저장된 데이터들은 새로고침하면 사라짐!

 

1주차 19강부터 Database와 SQL을 사용해서 데이터를 저장하고 불러오는 실습을 했다.

3] 

중복코드가 많은 Memo Project의 코드들을 3 Layer Architecture에 따라 3개로 분리하는 실습을 했다.

코드가 굉장히 간결해졌다. (따라 쓴 코드지만 진짜 개발을 한 느낌..!)

[MemoController]

package com.sparta.memo.controller;

import com.sparta.memo.Service.MemoService;
import com.sparta.memo.dto.MemoRequestDto;
import com.sparta.memo.dto.MemoResponseDto;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api")
public class MemoController {


    private final MemoService memoService;
    //final이기 때문에 초기화가 되야하기 때문에 하단에 생성자를 만듬
    public MemoController(MemoService memoService) { // Bean 에서 만든 객체로 넣어줌
        this.memoService = memoService;
    } //생성자의 파라미터를 통해서 받아 온 다음에 초기화가 진행!

    @PostMapping("/memos")
    public MemoResponseDto createMemo(@RequestBody MemoRequestDto requestDto) {
        return memoService.createMemo(requestDto);
    }

    @GetMapping("/memos")
    public List<MemoResponseDto> getMemos() {
        return memoService.getMemos();
    }

    @PutMapping("/memos/{id}")
    public Long updateMemo(@PathVariable Long id, @RequestBody MemoRequestDto requestDto) {
        return memoService.updateMemo(id, requestDto);
    }

    @DeleteMapping("/memos/{id}")
    public Long deleteMemo(@PathVariable Long id) {
        return memoService.deleteMemo(id);
    }
}

[MemoRepository]

package com.sparta.memo.repository;

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.stereotype.Repository;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
//데이터베이스 작업
@Repository
public class MemoRepository {

    private final JdbcTemplate jdbcTemplate;

    public MemoRepository(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public Memo save(Memo memo) {
        // 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);

        return memo;
    }

    public List<MemoResponseDto> findAll() {
        // 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);
            }
        });
    }

    public void update(Long id, MemoRequestDto requestDto) {
        String sql = "UPDATE memo SET username = ?, contents = ? WHERE id = ?";
        jdbcTemplate.update(sql, requestDto.getUsername(), requestDto.getContents(), id);
    }

    public void delete(Long id) {
        String sql = "DELETE FROM memo WHERE id = ?";
        jdbcTemplate.update(sql, id);

    }
    public 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);
    }


}

[MemoService]

package com.sparta.memo.Service;

import com.sparta.memo.dto.MemoRequestDto;
import com.sparta.memo.dto.MemoResponseDto;
import com.sparta.memo.entity.Memo;
import com.sparta.memo.repository.MemoRepository;
import org.springframework.stereotype.Service;

import java.util.List;
@Service
//@Component //Bean으로 등록
// @RequiredArgsConstructor : 롬복으로 잡는 방법
//변환, 전달, 확인 작업
public class MemoService {
    //JdbcTemplate은 Spring에서 관리가 되고 있음!

    private final MemoRepository memoRepository; // 롬복으로 주입 시 final 필수!
    //Method로 주입받는 방법
    //@Autowired 달고 (Spring Container에 의해서 관리되는 Bean class만 주입이 가능함!
//    public void 메서드이름(MemoRepository memoRepository) {
//        this.memoRepository = memoRepository;
//    } //생성자의 파라미터를 통해서 받아 온 다음에 초기화가 진행!


    //final이기 때문에 초기화가 되야하기 때문에 하단에 생성자를 만듬
    public MemoService(MemoRepository memoRepository) {
        this.memoRepository = memoRepository;
    } //생성자의 파라미터를 통해서 받아 온 다음에 초기화가 진행!

    public MemoResponseDto createMemo(MemoRequestDto requestDto) {
        // RequestDto -> Entity
        Memo memo = new Memo(requestDto);

        // DB 저장
        Memo saveMemo = memoRepository.save(memo);

        // Entity -> ResponseDto
        MemoResponseDto memoResponseDto = new MemoResponseDto(memo);

        return memoResponseDto;
    }

    public List<MemoResponseDto> getMemos() {
        // DB 조회
        return memoRepository.findAll();

    }

    public Long updateMemo(Long id, MemoRequestDto requestDto) {

        // 해당 메모가 DB에 존재하는지 확인
        Memo memo = memoRepository.findById(id);
        if(memo != null) {
            // memo 내용 수정
            memoRepository.update(id, requestDto);
            return id;
        } else {
            throw new IllegalArgumentException("선택한 메모는 존재하지 않습니다.");
        }
    }


    public Long deleteMemo(Long id) {
        // 해당 메모가 DB에 존재하는지 확인
        Memo memo = memoRepository.findById(id);

        if(memo != null) {
            // memo 삭제
            memoRepository.delete(id);
            return id;
        } else {
            throw new IllegalArgumentException("선택한 메모는 존재하지 않습니다.");
        }
    }
}
 
어려웠던 내용😵‍💫

사실 Java 언어 인터페이스의 개념도 모른 상태로 Spring 강의로 넘어 온 상태라 3 Layer Architecture로 코드를 작성했을 경우

아직은 어떻게 서로 값을 넘겨주는지 잘 모르겠다.

 

Bean을 사용해서 의존성 주입과 같이 실습했는데 오늘 수업을 들은 2주차의 내용들은 아직 전부 어려운 것 같다.

 

궁금&부족한 내용❓

1주차 강의를 끝내고 SQL 과제를 마무리했는데 앞서서 수업들었던 SQL코드가 하나도 생각이 안나서 스스로 작성할 수 없었다.

예제를 보고 작성하고 답안을 보고 작성하면서 이해했는데 이 부분은 혼자 다시한번 써봐야겠다.

느낀 점💡

처음 객체가 이해가 안되어서 혼란스러웠던 시절이 떠오른다.

고작 2-3주 전이지만..! Spring을 사용함으로서 객체지향에 대해 개념이 이제는 좀 잡혀가는 것 같다.

 

Spring의 기능을 사용하다보면 어떻게든 코드는 간결해진다.

앞으로도 모른다고 포기하지말고! 꾸준히 하다보면 깨우치는 날이 있을 거라고 믿는다!

화이팅이다!! :)

'📌TIL [Today I Learn]' 카테고리의 다른 글

[TIL] 23년 6월 16일 금요일  (0) 2023.06.16
[TIL] 23년 6월 15일 목요일  (0) 2023.06.15
[TIL] 23년 6월 13일 화요일  (0) 2023.06.13
[TIL] 23년 6월 12일 월요일  (0) 2023.06.12
[TIL] 23년 6월 09일 금요일  (0) 2023.06.09