[JPA] 리턴타입이 옵셔널(Optional)인 이유는?
JPA를 사용 중 아래 코드를 만났고 의문이 생겼다.
1 | final Optional<TodoEntity> original = repository.findById(entity.getId()); |
왜 꼭 Optional로 리턴타입을 감싸줘야하는걸까?
그냥 리턴타입만 쓰면 안될까?
1 | final TodoEntity original = repository.findById(entity.getId()); |
이런식으로 말이다.
위처럼 옵셔널(Optional)을 빼버리니 바로 IDE가 에러를 알려주었다.
1 | Type mismatch: cannot convert from Optional<TodoEntity> to TodoEntity |
왜 이런 에러가 발생하는 걸까?
원인은 바로 CrudRepository 인터페이스였다.
갑자기 CrudRepository라고?
Repository 인터페이스를 만들때 JPA를 쓰기 위해서 JpaRepository를 상속받는다.
JpaRepository인터페이스에서 find와 관련된 메서드를 알기위해서는 CrudRepository를 확인하라고 적혀있다.
- JpaRepository 인터페이스
1 | /** |
CrudRepository 인터페이스
CrudRepository 인터페이스에서 findById 메서드를 확인해보면 리턴값이 Optional 타입으로 고정되어있다.
그래서 바로 IDE가 에러를 알려주었다. 그렇다면 Optional를 쓰면 좋은 점이 뭘까?
1 | /** |
Optional 쓰면 좋은 점?
Optional은 Java 8에 추가되었다. 이전 자바버전에서는 사용 불가능하다.
Optional은 고통스러운 null 처리를 도와주는 Wrapper 클래스이다.
코드 예시를 보자.
1 | class Person { |
또는 try catch문을 이용해서 null을 처리할 수 있도 있고 다양한 NPE 처리 방법이 있다.
그런데 만약 필드가 많다면? 모든 필드를 NULL처리를 해줘야한다.
이때 Optional 클래스와 해당 클래스가 제공하는 orElse 메서드 또는 orElseGet 메서드를 이용하면 쉽게 NPE 처리가 가능하다.
메서드명 | 특징 |
---|---|
orElseThrow(NullPointerException::new) | null이라면 함수형 파라미터로 생성한 예외(NullPointerException)를 발생시킨다. |
orElse(person) | null이면 파라미터(person)를 반환한다. 이때 파라미터(person)은 해당 값이 null이든지 말든지 항상 미리 생성된다. |
orElseGet | null이면 파라미터(person)를 반환한다. 이때 파라미터(person)은 해당 값이 null 일때만 생성된다. 즉 미리 생성되지 않는다. |