Spring Data JDBC나 JPA를 구현할 때
CrudRepository나 JpaRepository를 사용했었는데,
이때 각 Repository에서 제공하는 기능
(ex. findById)
외 다른 기능을 custom하여 사용할 때
Entity 클래스의 wrapper 클래스로
Optional 클래스를 사용했었다.
이 Optional 클래스의 역할이 궁금하여
좀 더 찾아봤다.
Optional 클래스는 Java 8부터 지원하는 클래스로
여기
Java 개발자들에게 고질병인 NullPointException
을
방지할 수 있도록 도와준다고 한다.
null이 올 수 있는 값을 감싸는 wrapper 클래스로
generic으로 들어온 값들을 Optional 클래스 내부에
저장하기 때문에 값이 null이라도 NullPointException
가 발생하지 않는다.
어떤 데이터가 절대 null이 아닌경우
static factory method인 of를 통해 생성할 수 있다.
of 메서드는 T 타입의 value를 받고
T타입을 필요로 하는 생성자를 반환한다.
T타입을 받는 생성자는
Objects.requireNonNull
메서드를 통해
들어온 값이null이 아니라는것을 보장한다.
데이터가 null일 수도 있고 아닐 수도 있는 경우에
ofNullable 메서드를 통해 생성한다.
orElse
는 파라미터로 값을 받고
orElseGet
은 파라미터로 함수형 인터페이스를 받는다고 한다.
Optional<String> opt = Optional.ofNullable(Entity.getName());
String name = opt.orElse("익명");
orElse
를 통해 null일 경우 안에 들어오는 값을 return한다.
orElse
외에도 orElseGet
과 lambda식을 활용해
null 검사를 쉽게 표현할 수 있다.
그래서 왜쓰냐?
고 한다면
일단 가독성이 좋아지고, 코드가 null-safe해진다고 한다.
나의 경우 이때까지 배운 내용에서
Service 클래스의 entity update 메소드에 사용되었었는데
...
public class Service{
...
public Entity updateEntity(Entity entity){
Entity findEntity = repository.findById(entity.getId());
Optional.ofNullable(entity.getName())
.ifPresent(name -> findEntity.setName(name));
...
}
}
위 코드는
ofNullable
을 통해 null일지 아닐지 모를 name을 넣고
ifPresent
를 통해 name이 null이 아니면,
findEntity에 name을 setter를 통해 설정한다.
PATCH method의 경우 Entity의 모든 필드값이 아니라
원하는 필드값만 update하는 경우도 있기 때문에
각 필드별로 null을 파악해서 update하는 것이다.
이를 통해 null-safe해 진 것.