2011-12-24 3 views
45

여기에 코드입니다.Spring Data JPA Repository에서 save() 후에 리턴 된 인스턴스를 사용해야하는 이유는 무엇입니까?</p> <pre><code>@Repository public interface AccountRepository extends JpaRepository<Account, Long> {} </code></pre> <p><em>JpaRepository</em> 스프링 데이터 JPA 프로젝트에서 :

여기
account ID is 0 and for returned account ID is 1 

가 CrudReporsitory.save 내지() 자바 독 :

주어진 엔티티를 저장 여기

public class JpaAccountRepositoryTest extends JpaRepositoryTest { 
    @Inject 
    private AccountRepository accountRepository; 

    @Inject 
    private Account account; 

    @Test 
    @Transactional 
    public void createAccount() { 
     Account returnedAccount = accountRepository.save(account); 

     System.out.printf("account ID is %d and for returned account ID is %d\n", account.getId(), returnedAccount.getId()); 
    } 
} 

의 결과이다 : 여기

는 시험 번호이다. 저장 조작으로 엔티티 인스턴스가 완전히 변경되었을 수 있으므로 리턴 된 인스턴스를 추가 조작에 사용하십시오. 우리가 원래 대신 반환 된 인스턴스를 사용해야 할 이유

@Transactional 
    public T save(T entity) { 
      if (entityInformation.isNew(entity)) { 
        em.persist(entity); 
        return entity; 
      } else { 
        return em.merge(entity); 
      } 
    } 

그래서, 질문은 :

여기에 스프링 데이터 JPA에서 SimpleJpaRepository의 실제 코드는? (예, 우리는해야만합니다. 그렇지 않으면 분리 된 인스턴스로 작업을 계속합니다. 이유는 무엇입니까?)

원래의 EntityManager.persist() 메서드는 void를 반환하므로 인스턴스가 지속성 컨텍스트에 연결됩니다. 어떤 프록시 마술은 저장소를 저장하기 위해 계정을 전달하면서 발생합니까? Spring Data JPA 프로젝트의 아키텍처 제한 사항입니까?

답변

48

CrudRepository 인터페이스의 save(…) 인터페이스는 어떤 상태에 있더라도 엔티티를 단순히 저장하는 것으로 가정되므로, (JPA의 경우와 마찬가지로) 저장소가 차별화 되더라도 실제 상점 특정 구현을 노출하지 않아야합니다. 새로운 엔티티와 기존 엔티티 사이에 업데이트됩니다. 그렇기 때문에이 방법은 실제로 save(…)이 아니며 create(…) 또는 update(…)이 아닙니다. 실제로는 merge(…)이 호출 될 때 JPA가 잠재적으로 수행하는 것과 완전히 다른 인스턴스를 반환하도록 저장소 구현을 허용하기 위해이 메서드의 결과를 반환합니다.

일반적으로 실제 구현과 관련하여 관대 한 방법으로 JPA에 대한 방법을 구현하는 것은 API 결정에 더 가깝습니다. 전달 된 엔티티에 대해 수행 된 추가 프록시 마샬 러는 없습니다.

+0

새로운 엔티티에 대한 반품 결과를 사용하지 않는 것이 안전할까요? – danidacar

+2

반환 된 Object 상태에 대한 설명서는 어디에 있습니까? 즉, 업데이트 된 필드 (타임 스탬프)를 반환하는 경우가 있습니다. 필드가 DB에서 업데이트되지 않는 경우가 있습니다. – mmcrae

9

두 번째 부분을 놓쳤습니다. 엔티티가 새 것이 아니라면 merge이 호출됩니다. merge은 동일한 ID를 사용하여 첨부 된 엔터티에 인수의 상태를 복사하고 첨부 된 엔터티를 반환합니다. 엔티티가 새롭지 않고 반환 된 엔티티를 사용하지 않으면 분리 된 엔티티를 수정하게됩니다.

+0

예, 동의합니다. 적어도이 경우 EntityManager와 호환됩니다. 이 메서드의 이름을 saveOrMerge()로 바꾸는 것이 더 좋을까요? – akazlou

+0

Object의 일시적인 멤버는 어떻게됩니까? 병합 할 경우, 나는 새로운 실제 Object (솔직하게는 상관하지 않음)를 얻지 만, 원래 Object의 일시적인 값을 모두 잃어 버립니다. –

관련 문제