복붙노트

[SPRING] Spring Data JPA - @Transactional없이 가져온 Lazy Loaded 컬렉션

SPRING

Spring Data JPA - @Transactional없이 가져온 Lazy Loaded 컬렉션

내 예상은 게으른로드 된 컬렉션은 트랜잭션 범위 내에서 컬렉션에 액세스 할 때 가져와야한다는 것입니다. 예를 들어 컬렉션을 가져 오려면 foo.getBars.size ()를 호출 할 수 있습니다. 활성 트랜잭션이 없으면 다음과 같은 오류 메시지와 함께 예외가 발생합니다.

그러나 최근 응용 프로그램의 동작이 다른 것으로 나타났습니다. 나는 "data-jpa"시동기와 함께 Spring Boot 1.5.1을 사용하고있다. 과거에 Spring Boot를 사용했지만 data-jpa 스타터는 저에게 새로운 것입니다.

다음과 같은 경우를 고려하십시오. 나 게으른로드 ManyToMany 컬렉션이 있습니다.

@SuppressWarnings("serial")
@Entity
@Table(name = "foo")
public class Foo implements java.io.Serializable {
    ....
    private Set<Bar> bars = new HashSet<Bar>(0);
    ....

    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinTable(name = "foo_bar_map",
        joinColumns = {@JoinColumn(name = "foo_id", nullable = false, updatable = false)},
        inverseJoinColumns = {@JoinColumn(name = "bar_id", nullable = false, updatable = false)})
    public Set<Bar> getBars() {
        return this.bars;
    }

    public void setBar(Set<Bar> bars) {
        this.bars = bars;
    }

내 서비스 방법이 트랜잭션으로 표시되어 있지 않지만로드 된 컬렉션에 액세스하고 있습니다.

@Service
public class FooServiceImpl implements FooService {

    @Autowired
    private FooRepository fooRepo;


    @Override
    public FooDTO findById(int fooId) {
        Foo foo = fooRepo.findOne(fooId);
        // The FooDTO constructor will access foo.getBars()  
        return new FooDTO(foo);
    }

그리고 FooDTO 생성자에 대한 컨텍스트

public FooDTO(Foo foo) {
    ...
    for (Bar bar : foo.getBars()) {
        this.bars.add(bar);
    }
}

내 기대와 과거의 경험과는 달리이 코드는 성공적으로 실행되고 컬렉션을 가져옵니다. 또한 서비스 메소드에 중단 점을 던지면 코드를 한 단계 씩 실행하고 fooRepo를 호출 한 후 막대를 가져 오는 SQL 문을 로그에서 볼 수 있습니다. fooRepo에 전화를 건 후 거래가 종료 될 것으로 예상됩니다.

여기 무슨 일 이니?

해결법

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

    1.스프링 부트는 기본적으로 OpenEntityManagerInView 인터셉터를 사용합니다. spring.jpa.open-in-view 속성을 false로 설정하여 해제 할 수 있습니다.

    스프링 부트는 기본적으로 OpenEntityManagerInView 인터셉터를 사용합니다. spring.jpa.open-in-view 속성을 false로 설정하여 해제 할 수 있습니다.

    이 (및 기타) JPA 등록 정보에 대한 참조 문서를 참조하십시오.

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

    2.트랜잭션이 열려 있는지 확인하기 위해 로깅을 켤 수 있습니다.

    트랜잭션이 열려 있는지 확인하기 위해 로깅을 켤 수 있습니다.

    org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction
    

    또는

    org.hibernate.engine.transaction.internal.jta.JtaTransaction
    

    또한 중단 점을 설정하고이 정적 메소드를 사용하여 트랜잭션이 열려 있는지 확인할 수 있습니다.

    org.springframework.transaction.support.TransactionSynchronizationManager.isActualTransactionActive()
    
  3. from https://stackoverflow.com/questions/42584454/spring-data-jpa-lazy-loaded-collection-fetched-without-transactional by cc-by-sa and MIT license