JPA findById方法和getOne方法的區別說明

findById方法和getOne方法區別

Jpa基礎的CRUD方法繼承自接口CrudRepository<T, ID>,包含以下方法:

<S extends T> S save(S entity);
<S extends T> Iterable<S> saveAll(Iterable<S> entities);
Optional<T> findById(ID id);
boolean existsById(ID id);
Iterable<T> findAll();
Iterable<T> findAllById(Iterable<ID> ids);
long count();
void deleteById(ID id);
void delete(T entity);
void deleteAll(Iterable<? extends T> entities);
void deleteAll();

getOne()方法是JpaRepository接口中定義的

源碼如下:

/**
 * 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.
 */
T getOne(ID id);

網上找的源碼:

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

由getOne方法的源碼可見,getOne方法會返回一個和給定id匹配的實體的引用,方法實際是調用getReference方法,也就是說加載策略是延遲加載,直到調用這個對象的時候才真正從數據庫中進行查詢(x_x)。

再看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 = this.getQueryHints().withFetchGraphs(this.em).asMap();
        return Optional.ofNullable(type == null ? this.em.find(domainType, id, hints) : this.em.find(domainType, id, type, hints));
    }
}

findById實際上調用的是find方法,采用立即加載方式,執行這條查詢語句的時候就會立刻從數據庫中進行查詢,不過findById方法返回的是一個Optional,需要對這個Optional調用.get()方法才能得到需要的實體。

總結就是getOne方法是懶加載,直到調用它返回的實體時才會對數據庫進行查詢,findById是立即加載,主要調用方法就會去數據庫查詢。getOne方法直接返回一個實體,findById方法返回一個Optional,需要調用.get()方法獲取實體。

spring-data-jpa中findById()的使用

springboot 2.x 版本後,較之前的版本在此方法的使用上有差:

如果找到匹配的id數據,則賦值給foo;否則則將括號中的對象賦值給foo。

Foo foo = repository.findById(id)
                    .orElse(null);
Foo foo = repository.findById(id)
                    .orElse(new Object());

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。

推薦閱讀: