[hibernate] Hibernate : session.get과 session.load의 차이점

API에서 프록시와 관련이 있음을 알 수 있습니다. 하지만 프록시에 대한 많은 정보를 찾을 수 없었고 호출 session.getsession.load. 누군가 나를 참조 페이지로 설명하거나 안내해 주시겠습니까?

감사합니다!!



답변

로부터 최대 절전 모드 포럼 :

이것은 Hibernate in Action 책에서 발췌 한 것입니다. 잘 읽었어요 ..


식별자로 객체 검색 다음 Hibernate 코드 스 니펫은 데이터베이스에서 사용자 객체를 검색합니다.

User user = (User) session.get(User.class, userID);

get () 메서드는 식별자가 클래스의 단일 인스턴스를 고유하게 식별하기 때문에 특별합니다. 따라서 응용 프로그램에서 식별자를 영구 개체에 대한 편리한 핸들로 사용하는 것이 일반적입니다. 식별자 별 검색은 개체를 검색 할 때 캐시를 사용하여 개체가 이미 캐시 된 경우 데이터베이스 적중을 방지 할 수 있습니다. Hibernate는 또한 load () 메소드를 제공합니다 :

User user = (User) session.load(User.class, userID);

load () 메서드는 오래되었습니다. 사용자 요청으로 인해 Hibernate의 API에 get ()이 추가되었습니다. 차이점은 사소합니다.

load ()가 캐시 또는 데이터베이스에서 객체를 찾을 수 없으면 예외가 발생합니다. load () 메서드는 null을 반환하지 않습니다. get () 메서드는 객체를 찾을 수없는 경우 null을 반환합니다.

load () 메서드는 실제 영구 인스턴스 대신 프록시를 반환 할 수 있습니다. 프록시는 처음 액세스 할 때 실제 개체의로드를 트리거하는 자리 표시 자입니다. 반면에 get ()은 프록시를 반환하지 않습니다. get ()과 load () 중 하나를 선택하는 것은 쉽습니다. 영구 객체가 존재하고 존재하지 않는 것이 예외적 인 것으로 간주된다면 load ()가 좋은 옵션입니다. 주어진 식별자를 가진 영구 인스턴스가 있는지 확실하지 않은 경우 get ()을 사용하고 반환 값을 테스트하여 null인지 확인합니다. load ()를 사용하면 추가 의미가 있습니다. 애플리케이션은 영구 상태를 검색하기 위해 데이터베이스에 연결하지 않고도 영구 인스턴스에 대한 유효한 참조 (프록시)를 검색 할 수 있습니다. 따라서 load ()는 캐시 나 데이터베이스에서 영구 객체를 찾지 못하면 예외를 throw하지 않을 수 있습니다. 나중에 프록시에 액세스 할 때 예외가 발생합니다. 물론 식별자로 객체를 검색하는 것은 임의의 쿼리를 사용하는 것만 큼 유연하지 않습니다.


답변

음, 적어도 nhibernate에서 session.Get (id)는 데이터베이스에서 객체를로드하는 반면 session.Load (id)는 서버를 떠나지 않고 프록시 객체 만 생성합니다. POCO (또는 POJO :)의 다른 모든 지연로드 된 속성처럼 작동합니다. 그런 다음이 프록시를 개체 자체에 대한 참조로 사용하여 관계 등을 만들 수 있습니다.

Id 만 유지하고 필요한 경우 나머지를로드하는 개체가있는 것처럼 생각하십시오. 관계 (예 : FK)를 생성하기 위해 전달하는 경우 ID 만 있으면됩니다.


답변

session.load ()는 데이터베이스에 접속하지 않고 항상 “proxy”(Hibernate 용어)를 반환합니다. Hibernate에서 proxy는 주어진 식별자 값을 가진 객체이고, 그것의 속성은 아직 초기화되지 않았으며, 단지 임시 가짜 객체처럼 보입니다. 행이 없으면 ObjectNotFoundException이 발생합니다.

session.get ()은 항상 데이터베이스를 검색하고 프록시가 아닌 데이터베이스 행을 나타내는 개체 인 실제 개체를 반환합니다. 행이 없으면 null을 반환합니다.

이러한 방법을 사용한 성능도 diff를 만듭니다. 둘 사이 …


답변

추가 포인트 ::

Hibernate Session 클래스의 get 메소드는 객체가 데이터베이스뿐만 아니라 캐시에서도 발견되지 않으면 null을 반환합니다. load () 메서드는 객체가 데이터베이스뿐만 아니라 캐시에서도 발견되지 않고 null을 반환하지 않는 경우 ObjectNotFoundException을 throw합니다.


답변

“get”대신 “load”를 사용하는 간접적 인 결과는 버전 속성을 사용하는 낙관적 잠금이 예상대로 작동하지 않을 수 있다는 것입니다. 로드가 단순히 프록시를 만들고 데이터베이스에서 읽지 않으면 version 속성이로드되지 않습니다. 버전은 나중에 객체의 속성을 참조하여 선택을 트리거하는 경우에만로드됩니다. 그 동안 다른 세션에서 객체를 업데이트 할 수 있으며 세션에 낙관적 잠금 검사를 수행하는 데 필요한 원래 버전이 없으므로 세션의 업데이트가 경고없이 다른 세션의 업데이트를 덮어 씁니다.

다음은 동일한 식별자를 가진 개체로 작업하는 두 세션으로이 시나리오를 스케치하려는 시도입니다. DB에있는 객체의 초기 버전은 10입니다.

Session 1                  Session 2
---------                  ---------
Load object
Wait a while..
                           Load object
                           Modify object property
                           [triggers db 'select' -
                            version read as 10]
                           Commit
                           [triggers db update,
                            version modified to 11]
Modify object property
  [triggers db 'select' -
  version read as 11]
Commit
  [triggers db update,
  version modified to 12]

우리는 실제로 낙관적 잠금 예외와 함께 세션 1의 커밋이 실패하기를 원하지만 여기서 성공할 것입니다.

“load”대신 “get”을 사용하면 get이 즉시 선택을 실행하고 낙관적 잠금 검사를 위해 올바른 시간에 버전 번호가로드되기 때문에 문제를 해결할 수 있습니다.


답변

또한 객체가 없으면 예외가 발생하므로 load를 사용하는 동안주의해야합니다. 우리는 객체가 존재한다고 확신 할 때만 사용해야합니다.


답변

훌륭한 설명은에서 찾을 수 http://www.mkyong.com/hibernate/different-between-session-get-and-session-load

만일 Session.load () :
그것은 항상 “프록시”(최대 절전 용어를) 반환하지 않고 데이터베이스를 치는 것.
Hibernate에서 proxy는 주어진 식별자 값을 가진 객체이고, 그것의 속성은 아직 초기화되지 않았으며, 단지 임시 가짜 객체처럼 보입니다.
ID 값이 데이터베이스에 존재하지 않더라도 항상 주어진 ID 값을 가진 프록시 객체를 반환합니다. 그러나 데이터베이스에서 속성을 검색하여 프록시를 초기화하려고하면 select 문을 사용하여 데이터베이스에 충돌합니다. 행이 없으면 ObjectNotFoundException이 발생합니다.
session.get () :
항상 데이터베이스 (캐시에서 찾을 수없는 경우)를 검색하고 프록시가 아닌 데이터베이스 행을 나타내는 개체 인 실제 개체를 반환합니다.
행이 없으면 null을 반환합니다.