복붙노트

[SPRING] CrudRepository findOne ()과 JpaRepository getOne ()의 차이점

SPRING

CrudRepository findOne ()과 JpaRepository getOne ()의 차이점

getOne ()이 게으르며 findOne ()이 전체 엔티티를 즉시 가져옵니다. 디버깅 로그를 확인한 후 SQL Server에서 어떤 명령문이 실행되는지 확인하기 위해 모니터링을 활성화했습니다. getOne ()과 findOne ()이 동일한 쿼리를 생성하고 실행한다는 것을 알았습니다. 그러나 getOne ()을 사용할 때 값은 처음에는 null입니다 (당연히 ID는 제외).

두 사람 모두 데이터베이스에서 동일한 쿼리를 실행하면 아무도 말해 줄 수 없습니다. 왜 다른 쿼리를 사용해야합니까? 기본적으로 엔티티를 가져 오지 않고 모든 자식 / 특성을 가져올 수있는 방법을 찾고 있습니다.

EDIT1

엔티티 코드

DAO 코드 :

@Repository
public interface FlightDao extends JpaRepository<Flight, Long> {
}

디버깅 로그 findOne ()과 getOne ()

첫 번째 :

Chlebik 덕분에 문제를 확인할 수있었습니다. Chlebik이 말했듯이 getOne ()이 가져온 엔티티의 속성에 액세스하려고하면 전체 쿼리가 실행됩니다. 내 경우에는 한 번에 한 줄씩 움직여서 디버깅하는 동안 동작을 확인하고있었습니다. IDE 디버깅이 디버깅 목적으로 개체 속성에 액세스하려고 시도하는 동안 (또는 최소한 생각하고있는 것) 디버깅 트리거를 디버깅하는 동안 완전히 잊어 버렸습니다. 전체 쿼리 실행 디버깅을 중단하고 로그를 확인하면 모든 것이 정상적으로 보입니다.

getOne () vs findOne () (이 로그는 MySQL general_log에서 가져온 것이고 최대 절전 모드는 아닙니다.

디버깅 로그

디버깅 로그 없음

해결법

  1. ==============================

    1.이것은 단지 추측이지만 '순수 JPA'에는 getReference라는 EntityManager의 메소드가 있습니다. 그리고 ID가있는 엔티티 만 검색하도록 설계되었습니다. 그것의 사용은 대부분 전체 엔터티를 검색 할 필요없이 존재하는 참조 표시에 사용되었습니다. 어쩌면 코드가 더 알려줄 것입니다 :

    이것은 단지 추측이지만 '순수 JPA'에는 getReference라는 EntityManager의 메소드가 있습니다. 그리고 ID가있는 엔티티 만 검색하도록 설계되었습니다. 그것의 사용은 대부분 전체 엔터티를 검색 할 필요없이 존재하는 참조 표시에 사용되었습니다. 어쩌면 코드가 더 알려줄 것입니다 :

    // em is EntityManager
    Department dept = em.getReference(Department.class, 30);  // Gets only     entity with ID property, rest is null
    Employee emp = new Employee();
    emp.setId(53);
    emp.setName("Peter");
    emp.setDepartment(dept);
    dept.getEmployees().add(emp);
    em.persist(emp);
    

    나는 getOne이 같은 목적을 가지고 있다고 가정합니다. 생성 된 쿼리가 귀하가 물어 보는 것과 같은 이유는 무엇입니까? 음, JPA 성경에서 AFAIR - Mike Keith와 Merrick Schincariol의 Pro JPA2 - 거의 모든 단락에는 '행위는 공급 업체에 따라 다릅니다.'와 같은 내용이 포함되어 있습니다.

    편집하다:

    나 자신의 설정을했습니다. 마지막으로 필자는 어떤 식 으로든 getOne (entity.getId ())로 가져온 엔터티를 방해하면 SQL이 실행되도록 결론을 내렸다. 위의 코드에 표시된 것과 같은 관계 표시기와 같이 프록시를 작성하는 데만 사용하는 경우에는 아무 일도 일어나지 않으며 추가 SQL이 실행되지 않습니다. 그래서 나는 당신의 서비스 클래스에서이 엔티티 (getter를 사용하고 로그를 남긴다)로 무엇인가를한다고 가정하기 때문에이 두 메소드의 결과는 똑같이 보입니다.

    예제 코드가있는 ChlebikGitHub 도움이되는 질문 # 1 도움이되는 질문 # 2

  2. ==============================

    2.id로 엔티티를 제거하려고한다고 가정하십시오. SQL에서는 다음과 같은 쿼리를 실행할 수 있습니다.

    id로 엔티티를 제거하려고한다고 가정하십시오. SQL에서는 다음과 같은 쿼리를 실행할 수 있습니다.

    "delete form TABLE_NAME where id = ?". 
    

    그리고 Hibernate에서 먼저 엔티티의 관리 인스턴스를 가져 와서 EntityManager.remove 메소드에 전달해야한다.

    Entity a = em.find(Entity.class, id);
    em.remove(a);
    

    그러나 이렇게하면 삭제하기 전에 데이터베이스에서 삭제할 엔티티를 가져와야합니다. 정말 필요한가요?

    EntityManager.getReference 메쏘드는 데이터베이스를 질의하고 엔티티의 프로퍼티를 설정하지 않고 Hibernate 프록시를 반환한다. 반환 된 프록시의 속성을 직접 얻으려고하지 않는 한.

    메소드 JpaRepository.getOne은 EntityManager.find 메소드 대신 EntityManager.getReference 메소드를 사용합니다. 따라서 관리 객체가 필요할 때마다 데이터베이스를 쿼리 할 필요가 없으면 JpaRepostory.getOne 메서드를 사용하여 불필요한 쿼리를 제거하는 것이 좋습니다.

  3. ==============================

    3.findOne (id)를 사용하여 데이터베이스에 존재하는 id로 엔티티를 쿼리하면 null을 얻고 getOne (id)을 사용하면 null 필드가있는 객체를 얻을 수 있으므로 getOne (id) == null을 확인하면 작동하지 않습니다 예상대로

    findOne (id)를 사용하여 데이터베이스에 존재하는 id로 엔티티를 쿼리하면 null을 얻고 getOne (id)을 사용하면 null 필드가있는 객체를 얻을 수 있으므로 getOne (id) == null을 확인하면 작동하지 않습니다 예상대로

  4. ==============================

    4.데이터가 특정 ID에 대한 테이블을 찾지 못하면 findOne은 null을 반환하고 getOne은 javax.persistence.EntityNotFoundException을 반환합니다. 둘 다 자신의 장단점이 있습니다. 아래 예를 참조하십시오.

    데이터가 특정 ID에 대한 테이블을 찾지 못하면 findOne은 null을 반환하고 getOne은 javax.persistence.EntityNotFoundException을 반환합니다. 둘 다 자신의 장단점이 있습니다. 아래 예를 참조하십시오.

    결과를 안다면 요구 사항에 따라 업데이트 할 수 있습니다.

  5. from https://stackoverflow.com/questions/33218762/difference-between-crudrepository-findone-and-jparepository-getone by cc-by-sa and MIT license