본문 바로가기

SPRING/JPA

[ JPA | 강의 따라 공부하기 ] 4.find()와 getReference()의 차이

find()메소드

find 메소드는 EntityManager에서 조회 연산을 수행한다.

첫번째 파라미터로 엔티티 타입을 지정하고 두번째 파라미터로 식별자를 전달한다.

엔티티 매니저는 그 값을 조회해 쿼리를 만들어서 데이터 베이스의 객체를 가져오게 된다.

UserEntity userEntity = entityManager.find(UserEntity.class,email);

여기서 식별자는 @Id 어노테이션이 정의된 필드를 사용한다.

엔티티를 조회했을 때 식별자와 매핑되는 엔티티가 존재하면 엔티티 객체를 리턴하고 매핑되는 엔티티가 없으면 null을 리턴한다.

 

getReference()메소드

getReference메소드는 find메소드와 마찬가지로 EntityManager에서 조회 연산을 수행한다.

첫번째 파라미터로 엔티티 타입을 지정하고 두번째 파라미터로 식별자를 전달한다.

userEntity = entityManager.getReference(UserEntity.class,email);

여기서 식별자는 @Id 어노테이션이 정의된 필드를 사용한다.

getReference메소드는 프록시 객체를 리턴하며 메소드가 실행되는 시점에 쿼리를 실행하지 않는다.

실제쿼리는 최초로 데이터에 접근하는 시점에 실행된다.

프록시 객체를 EntityManager세션이 유지되는 상황에서 사용해야 객체를 세션 밖에서도 사용할 수 있다.

세션 안에서 한번도 데이터에 접근을 하지 않아서 데이터가 존재하지 않을 경우 EntityNotFoundException을 발생한다.

 

 @Override
    public Optional<UserEntity> getUser(String email) {
        EntityManager entityManager = CEntityManagerFactory.createEntityManger();
        // 조회만 할 경우 트랜잭션은 필요하지 않음
        System.out.println("checkpoint 1");

        UserEntity userEntity = entityManager.find(UserEntity.class, email);
        System.out.println("checkpoint 2");
        System.out.println(userEntity.getClass().getName());

        System.out.println("checkpoint  3");
        entityManager.close();

        System.out.println("checkpoint 4");
        return Optional.ofNullable(userEntity);
    }

    @Override
    public Optional<UserEntity> getReferenceUser(String email) {

        EntityManager entityManager = CEntityManagerFactory.createEntityManger();
        // 조회만 할 경우 트랜잭션은 필요하지 않음
        UserEntity userEntity;
        try {
            System.out.println("checkpoint 1");
            // getReference 메소드를 사용하면 엔티티 객체가 실제 사용되는 시점에 쿼리가 실행됨
            userEntity = entityManager.getReference(UserEntity.class, email);
            System.out.println("checkpoint 2");
            // 아래 코드가 주석처리되면 오류가 발생하고, 주석을 해제하고 실행하면 오류가 발생하지 않음
            userEntity.getName();
            System.out.println("checkpoint 3");
        } finally {
            entityManager.close();
            System.out.println("checkpoint 4");
        }
        /*
        콘솔 출력 내용을 보면 프록시 객체인 것을 확인할 수 있음
        만약 Entity 클래스를 final 로 선언했다면 프록시 객체를 생성할 수 없어서 오류가 발생함
         */
        System.out.println("checkpoint 5");
        System.out.println(userEntity.getClass().getName());

        /*
         세션이 이미 종료되어 있어서 값을 가져올 수 없음
         이 값을 사용하기 위해서는 entityManager 가 종료되기 전에 사용을 한번 해줘야 함
         */
        System.out.println("checkpoint 6");
        System.out.println(userEntity.getName());

        return Optional.ofNullable(userEntity);

 

 

 

*학습 자료 출처 : 어라운드 허브 스튜디오