README.md
에 작성README.md
에 첨부✅ 일정 생성(일정 작성하기)
할일
, 작성자명
, 비밀번호
, 작성/수정일
을 저장작성/수정일
은 날짜와 시간을 모두 포함한 형태✅ 전체 일정 조회(등록된 일정 불러오기)
수정일
(형식 : YYYY-MM-DD)작성자명
수정일
기준 내림차순으로 정렬하여 조회✅ 선택 일정 조회(선택한 일정 정보 불러오기)
✅ 선택한 일정 수정
할일
, 작성자명
만 수정 가능비밀번호
를 함께 전달합니다.은 변경할 수 없으며,
수정일` 은 수정 완료 시, 수정한 시점으로 변경합니다.✅ 선택한 일정 삭제
비밀번호
를 함께 전달합니다.이름
외에 이메일
, 등록일
, 수정일
정보를 가지고 있습니다.페이지 번호
와 페이지 크기
를 쿼리 파라미터로 전달하여 요청하는 항목을 나타냅니다.페이지 번호
와 크기
를 기준으로 모두 조회작성자 이름
이 포함✅ 설명
HTTP 상태 코드(링크)
와 에러 메시지
를 포함한 정보를 사용하여 예외를 관리할 수 있습니다.@ExceptionHandler
를 활용하여 공통 예외 처리를 구현할 수도 있습니다.✅ 조건
비밀번호
가 일치하지 않을 때 예외가 발생합니다.무결성을 보장
하고 애플리케이션의 예측 가능성을 높여줍니다.@Valid
어노테이션을 이용할 수 있습니다.할일
은 최대 200자 이내로 제한, 필수값 처리비밀번호
는 필수값 처리이메일
정보가 형식에 맞는지 확인작성일을 내가 직접 수기로 입력하지 않더라도 자동으로 배치시키기 위해 DEFAULT 를 사용했다.
또한 NULL 값이면 안된다고 생각해서 NOT NULL 을 같이 사용했다.
그랬더니 api 를 돌렸을때 500 에러 ( Column 'created_at' cannot be null ) 가 발생했다.
@Override
public Schedule save(Schedule schedule) {
// INSERT Query: 문자열을 직접 작성하지 않아도 됨
SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate);
// schedule 이라는 테이블에 Insert 하겠다 + 이 테이블의 key 값은 id 라는 이름으로 설정되어 있다.
jdbcInsert.withTableName("schedule").usingGeneratedKeyColumns("schedule_id");
SimpleJdbcInsert
가 Java 객체에서 만든 필드명을 기준으로 자동으로 컬럼을 추론해서 insert
하려고 할 때,parameters
를 직접 넣었지만,SimpleJdbcInsert
는 내부적으로 columnMapping
을 추론할 수 있다.created_at = null
이 다시 포함될 수 있음.MySQL의 DEFAULT CURRENT_TIMESTAMP
는 컬럼을 아예 INSERT
에서 생략할 때만 동작한다.
그런데 내 코드는 SimpleJdbcInsert
가 자동으로 모든 필드를 매핑할 때 createdAt = null
값이 부여되었다.
따라서 DEFAULT가 무시되고, null이 그대로 들어가면서 에러가 나는 것이었다.
" SimpleJdbcInsert
에 insert할 컬럼을 명시적으로 지정하기 "
SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate)
.withTableName("schedules")
.usingGeneratedKeyColumns("schedule_id")
.usingColumns("schedule_title", "content", "schedule_password", "member_id"); // 👈 여기 명시!
이렇게 하면, created_at
은 명시적으로 제외되기 때문에
DB에서 DEFAULT CURRENT_TIMESTAMP
가 정상적으로 동작하게 된다.
SimpleJdbcInsert
는 usingColumns()
을 지정하지 않으면
→ Map
의 모든 key와 데이터베이스 테이블의 모든 컬럼을 비교해서 자동 매핑하려고 시도함.
→ 이 과정에서 created_at = null 이 들어가 버리는 경우가 생김
Scehdule 클래스에서 생성자를 만들었다.
updated_at
이 없어서 Expected 1 argument but found 5 에러가 나고 있다.
너무너무 비효율적이라고 생각했다.
쿼리에서 가져온 데이터는 많고,
그걸 전부 ScheduleResponseDto
생성자에 맞춰서 전부 다 써야한다니?
그래서 필요한것만 쓰고 싶어서 아래와 같이 해결했다.
필드가 많고 일부만 필요하여,
생성자 주입 말고 setter 방식으로 구현했다.
앞선 과정에서 Schedule 에 Expected 7 arguments but found 0 에러가 났다.
Schedlue 클래스에 기본생성자(매개변수 없는 생성자) 가 없어서 생기는 에러로 판단하여
NoArgsConstructor
을 추가하여 Lombok
이 자동으로 기본 생성자를 만들어주게끔 했다.
에러는 일단락시켰지만.... 조금 걱정이 됐다.
NoArgsConstructor
은 매개변수를 체크해주지 않아서 위험할 것 같은데, 권장되는 어노테이션일까?
NoArgsConstructor 은 조사한 바로는,
DTO, Entity, ORM 매핑 객체에서는 꽤 자주 쓰이는 어노테이션이지만,
도메인 로직을 담은 객체나, 무조건 필드가 필수인 객체에서는 유의해야 한다고 한다.
나와 같은 경우는...
DB 에서 매핑해주는 용도로만 사용하기 때문에 적절한 사용이라고 생각한다.
entity객체 업데이트와 DB 업데이트를 별개의 stream으로 만들어서 스프링에는 반영이 되었으나, DB에 반영이 안될 수 도 있음.
--> @Transactional
을 사용해 같은 작업이라는걸 명시해 주기
ScheduleRepository
인터페이스에는 @Repository
을 넣을 필요 X
--> 구현체에만 적용하기
MemberUpdate
시 비밀번호 확인을 바로 해주고 있는데, 만약 dbPassword
가 없다면 NullPointerException
이 발생함
--> DB에서 값을 꺼낼때는 언제나 Optional
을 활용해 주기