아 이게 뭐임!

findById와 getById의 차이가 뭐임? [스프링JPA]

마로가마따 2022. 8. 17. 03:46

FindById와 GetById의 차이가 뭐임?

일단 JPA의 getById와 findById의 코드를 살펴보자.

 

JPA

 


# getById

* getById 코드

public T getById(ID id) {
    Assert.notNull(id, "The given id must not be null!");
    return this.em.getReference(this.getDomainClass(), id);
}

* getById 주석

Returns a reference to the entity with the given identifier. 
Depending on how the JPA persistence provider is implemented this is very likely to always return an instance and throw an javax.persistence.EntityNotFoundException on first access. 
Some of them will reject invalid identifiers immediately.

Params:
id – must not be null.
Returns:
a reference to the entity with the given identifier.
Since:
2.5

* 주석부분 한국어 번역

지정된 식별자가 있는 엔터티에 대한 참조를 반환합니다. 
JPA 지속성 공급자가 구현되는 방식에 따라 이는 항상 인스턴스를 반환하고 
첫 번째 액세스에서 javax.persistence.EntityNotFoundException을 던질 가능성이 매우 높습니다. 
그들 중 일부는 잘못된 식별자를 즉시 거부합니다.

매개변수:
id – null이 아니어야 합니다.
Returns:
주어진 식별자를 가진 엔티티에 대한 참조.
since:
2.5

무슨말인지 어려운데 차근차근 봐보면,

 

 

getById 코드는

CRUD와는 다르게 JPA에서는 Optional<T> 가 아닌 T가 반환값입니다.

JPA에서 리턴으로 무엇인가 반환되기를 믿는 것으로 보입니다.

매개변수로 전달된 ID에 해당하는 entity를 리턴하고 없을 경우 예외를 발생시킵니다.

(* javax.persistence.EntityNotFoundException)

 

id는 assert구문을 이용하여 null체크를 하고있습니다.

 

em.getReference문을 내부적으로 호출하는 것이 보입니다.

Returns: 에서 엔티티에 대한 참조를 반환한다고 주석에 명시되어있습니다.

 

 

em.getReference 주석부분

Get an instance, whose state may be lazily fetched.
If the requested instance does not exist in the database,
the EntityNotFoundException is thrown when the instance state is first accessed. 
(The persistence provider runtime is permitted to throw the EntityNotFoundException when getReference is called.) The application should not expect that the instance state will be available upon detachment, unless it was accessed by the application while the entity manager was open.
Params:
entityClass – entity class
primaryKey – primary key
Returns:
the found entity instance
Throws:
IllegalArgumentException – if the first argument does not denote an entity type or the second argument is not a valid type for that entity's primary key or is null
EntityNotFoundException – if the entity state cannot be accessed

* 주석부분 한국어 번역

상태를 느리게 가져올 수 있는 인스턴스를 가져옵니다.
요청한 인스턴스가 데이터베이스에 존재하지 않는 경우,
인스턴스 상태에 처음 액세스할 때 EntityNotFoundException이 발생합니다.
(지속 제공자 런타임은 getReference가 호출될 때 EntityNotFoundException을 던질 수 있도록 허용됩니다.) 
엔티티 관리자가 열려 있는 동안 애플리케이션에서 액세스하지 않는 한 애플리케이션은 분리 시 인스턴스 상태를 사용할 수 있을 것이라고 예상해서는 안 됩니다.
매개변수:
entityClass – 엔티티 클래스
PrimaryKey – 기본 키
보고:
발견된 엔티티 인스턴스
던짐:
IllegalArgumentException – 첫 번째 인수가 엔티티 유형을 나타내지 않거나 두 번째 인수가 해당 엔티티의 기본 키에 대한 유효한 유형이 아니거나 null인 경우
EntityNotFoundException – 엔티티 상태에 액세스할 수 없는 경우

 

 

주석을 읽어보면 getById는 인스턴스를 느리게 가져온다고 적혀있습니다. 식별자와 실제 객체의 주소를 가지고 있는 프록시 객체를 가져오기 때문입니다. 또한 프록시를 사용하기 때문에 실제 사용시에만 데이터베이스에 접근하게 됩니다. 이때문에 실제 액세스할 시점에 EntityNotFoundException을 throw하게 되는 것입니다.

 

 

 


 

# getOne..?

 

또한 이 getById는 getOne이라는 @Deprecated 된 함수가 있었습니다.

 

/**
 * Returns a reference to the entity with the given identifier. Depending on how the JPA persistence provider is
 * implemented this is very likely to always return an instance and throw an
 * {@link javax.persistence.EntityNotFoundException} on first access. Some of them will reject invalid identifiers
 * immediately.
 *
 * @param id must not be {@literal null}.
 * @return a reference to the entity with the given identifier.
 * @see EntityManager#getReference(Class, Object) for details on when an exception is thrown.
 * @deprecated use {@link JpaRepository#getById(ID)} instead.
 */
@Deprecated
T getOne(ID id);

* 주석부분 한국어 번역

주어진 식별자를 가진 엔터티에 대한 참조를 반환합니다. JPA 지속성 제공자가 어떻게 되는지에 따라
구현하면 항상 인스턴스를 반환하고 throw할 가능성이 매우 높습니다.
첫 번째 액세스 시 {@link javax.persistence.EntityNotFoundException}. 그들 중 일부는 잘못된 식별자를 거부합니다
즉시.

@param id는 {@literal null}이 아니어야 합니다.
@return 주어진 식별자를 가진 엔티티에 대한 참조.
예외가 발생하는 시기에 대한 자세한 내용은 @EntityManager #getReference(Class, Object)를 참조하세요.
@deprecated 대신 {@link JpaRepository#getById(ID)}를 사용하세요.

 

getById를 사용하라고 하네요. 적혀있는 주석으로 미루어보아 둘이 같은기능을 하는것으로 보입니다.

+옛날엔 getOne을 사용했다고 합니다.

 

 

 


# findById

 

* findById 코드

public Optional<T> findById(ID id) {
    Assert.notNull(id, "The given id must not be null!");
    Class<T> domainType = this.getDomainClass();
    if (this.metadata == null) {
        return Optional.ofNullable(this.em.find(domainType, id));
    } else {
        LockModeType type = this.metadata.getLockModeType();
        Map<String, Object> hints = new HashMap();
        this.getQueryHints().withFetchGraphs(this.em).forEach(hints::put);
        return Optional.ofNullable(type == null ? this.em.find(domainType, id, hints) : this.em.find(domainType, id, type, hints));
    }
}

* findById 주석

Retrieves an entity by its id.
Params:
id – must not be null.
Returns:
the entity with the given id or Optional#empty() if none found.
Throws:
IllegalArgumentException – if id is null.
ID로 엔티티를 검색합니다.
매개변수:
id – null이 아니어야 합니다.
Return:
주어진 ID를 가진 엔티티 또는 발견되지 않은 경우 Optional#empty().
Throw:
IllegalArgumentException – id가 null인 경우.

 

이 메서드는

실제로 데이터베이스에 도달하고 데이터베이스의 행에 대한 실제 개체 매핑을 반환합니다. 

데이터베이스에 레코드가 없는 경우 null을 반환합니다.

 

 

 


비교표

 

getOne() findById()
대상 엔터티에 대한 지연 로드된 참조 실제로 주어진 ID에 대한 엔티티를 로드합니다.
개체의 속성에 대한 액세스가 필요하지 않은 경우에만 유용합니다. 모든 속성에 액세스할 수 있도록 개체가 빠르게 로드됨
액세스 호출 시 실제 개체가 존재하지 않으면 EntityNotFoundException을 던집니다. 주어진 Id에 해당하는 실제 객체가 존재하지 않으면 null을 반환
더 나은 성능 데이터베이스에 대한 추가 왕복이 필요합니다.

표 출처:

(https://www.javacodemonk.com/difference-between-getone-and-findbyid-in-spring-data-jpa-3a96c3ff)

 


 

// 추가

Find와 Get의 의미차이

자료를 뒤지다 보니 몇몇 사람들은 Find와 Get의 의미를 구분지어 사용하려하는 것을 알게되었다.

 

약간 정리해보자면,

 

Find는 "찾다"이다. 무엇인가를 찾아본다는 것은 찾는 대상이 없을수도 있는 가능성을 내포한다. 따라서 우리가 매소드를 실행시켰을때, 해당함수를 호출하는 곳에서 데이터를 찾지못하는 경우의 예외를 처리해주어야한다.

 

Get은 "가져오다"이다. 이는 함수가 호출되면 무엇인가 결과가 리턴되기를 보장한다. 따라서 Get의 경우에는 결과를 찾지 못하면 즉시 exception 예외를 던진다. 

 

 

이걸 보면서 영단어에 내포되어있는 뜻을 코드에 적용되게 개발하기 때문에 이후에 그 코드를 보는 개발자는 쉽게 유추를 통해 무리없이 코드를 읽고 사용할수 있을 것 같다는 생각을 하게 되었다. 이러한 코드의 특성이 좋은 코드를 지향하는 하나의 디테일 요소가 아닐까하고 생각한다.

 

 

 

 

 

 

 

-끗-

 

 

 

 

 

 

 

반응형

'아 이게 뭐임!' 카테고리의 다른 글

영속성 컨텍스트가 뭐임!  (0) 2022.09.04
Telnet이 뭐임?  (0) 2022.04.19
JSON이 뭐임...!! (HTT...P..?)  (0) 2021.07.30
Generic 두개 이상의 변수 사용  (0) 2021.07.29
Generic이 뭐임!! [JAVA]  (0) 2021.07.28