programing

JPA Lazy Loading이 Spring boot에서 작동하지 않습니다.

bestprogram 2023. 7. 21. 21:45

JPA Lazy Loading이 Spring boot에서 작동하지 않습니다.

제가 구글을 많이 검색했는데 Spring Boot(최신 버전)에 게으른 로딩이 작동하지 않을 수 있다는 것이 정말 이상합니다.다음은 내 코드의 일부입니다.

내 리소스:

 public ResponseEntity<Page<AirWaybill>> searchAirWaybill(CriteraDto criteriaDto, @PageableDefault(size = 10) Pageable pageable{
airWaybillService.searchAirWaybill(criteriaDto, pageable);
        return ResponseEntity.ok().body(result);
}

내 서비스:

@Service
@Transactional
public class AirWaybillService {

//Methods

 public Page<AirWaybill> searchAirWaybill(AirWaybillCriteriaDto searchCriteria, Pageable pageable){
    //Construct the specification
            return airWaybillRepository.findAll(spec, pageable);
   }
}

내 엔티티:

@Entity
@Table(name = "TRACKING_AIR_WAYBILL")
@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@airWaybillId") //to fix Infinite recursion with LoadedAirWaybill class
public class AirWaybill{
//Some attributes
    @NotNull
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "FK_TRACKING_CORPORATE_BRANCH_ID")
    private CorporateBranch corporateBranch;
}

디버깅을 할 때에도 모든 laid loaded 속성이 로드됩니다.아래 이미지를 참조하십시오.

enter image description here

내 질문 중 하나는 잭슨이 그런 행동에 관여할 수 있을까 하는 것입니다.게으른 로딩을 활성화하기 위해 제가 놓쳤을 수 있는 방법이 있습니까?

편집

또 다른 질문은 디버거가 게으른 로딩을 망치는 데 관여할 수 있는가 하는 것입니다.

편집 2:

사양 빌드의 경우 다음과 같습니다.

public static Specification<AirWaybill> isBranchAirWayBill(long id){
    return new Specification<AirWaybill>() {
        @Override
        public Predicate toPredicate(Root<AirWaybill> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
            return cb.equal(root.join("corporateBranch",JoinType.LEFT).get("id"),id);
        }
    };
}

에서 " " " " " " " " " " " 를 사용합니다.@Transactional를 전달하는 입니다. 외 엔 클 료 좋 않 것 관 은 행 입 니 다 지 전 는 달 를 티 티 로 부 을 스 래 한 서 세 비 문 스 션 에 히 이search 초기화된 되어 있습니다.반면에 엔티티에는 세션이 닫히면 꺼낼 수 없는 초기화된 느린 컬렉션이 포함되어 있습니다.

모범 사례는 엔티티를 전송 개체에 매핑하고 이러한 전송 개체를 서비스에서 반환하는 것입니다(원시 엔티티가 아님).

SpringBoot는 기본적으로 활성화되어 있습니다.
= truespring.jpa.open-view = true
그것은 거래가 항상 열려 있다는 것을 의미합니다.사용하지 않도록 설정합니다.
자세한 내용은 여기를 참조하십시오.

대부분의 경우 서비스 내부에 있는 동안 디버깅을 수행하므로 트랜잭션이 여전히 활성화되어 있고 느린 로드가 트리거될 수 있습니다(레이지 요소에서 호출된 모든 메서드가 데이터베이스에서 가져오기를 트리거함).

문제는 거래 밖에 있는 동안에는 게으른 로딩이 발생할 수 없다는 것입니다.그리고 잭슨은 하나의 경계 밖에서 당신의 실체를 분석하고 있습니다.

사양을 작성할 때 필요한 모든 종속성을 가져오거나 사용해 보십시오.@Transactional리소스 수준에서 사용할 수 있습니다.

그러니까, LAY 페치 전략은 힌트일 뿐입니다.강제적인 조치가 아닙니다.간절기는 필수 사항:

LAY 전략은 데이터에 처음 액세스할 때 데이터를 느리게 가져와야 한다는 지속성 공급자 런타임에 대한 힌트입니다.구현은 LAY 전략 힌트가 지정된 데이터를 열심히 가져올 수 있습니다.

디버거를 사용할 때 변수 값에 액세스하려고 합니다.화면에서 작은 화살표를 클릭하는 순간 해당 변수의 값이 (느리게) 로드됩니다.

나는 당신이 Hibernate를 JPA로 사용하고 있다고 생각합니다.

규격에서:

EAGER 전략은 지속성 공급자 런타임에서 데이터를 열심히 가져와야 하는 요구 사항입니다.LAY 전략은 데이터에 처음 액세스할 때 데이터를 느리게 가져와야 한다는 지속성 공급자 런타임에 대한 힌트입니다.구현은 LAY 전략 힌트가 지정된 데이터를 열심히 가져올 수 있습니다.https://docs.jboss.org/hibernate/jpa/2.2/api/javax/persistence/FetchType.html

최대 절전 모드는 특히 OneToOne 및 ManyToOne 관계에서 소유하지 않는 쪽에서 가져오기 유형을 무시합니다.

정말 필요한 경우 최대 절전 모드에서 가져오기 유형 LAY를 사용하도록 강제하는 방법은 몇 가지 옵션이 있습니다.

  1. 가장 간단한 것은 일대일 관계를 가장하는 것입니다.수집을 느리게 로드하는 것이 단일 null 가능한 속성을 느리게 로드하는 것보다 훨씬 쉬우므로 이 방법은 작동하지만 일반적으로 복잡한 JPQL/HQL 쿼리를 사용하는 경우에는 매우 불편합니다.
  2. 다른 하나는 빌드 시간 바이트 코드 계측을 사용하는 것입니다.자세한 내용은 최대 절전 모드 설명서 19.1.7을 참조하십시오.게으른 속성 가져오기를 사용합니다.이 경우 @LazyToOne(LazyToOneOption)을 추가해야 합니다.NO_PROXY) 주석을 일대일 관계에 추가하여 게으르게 만듭니다.가져오기를 LAY로 설정하는 것만으로는 충분하지 않습니다.
  3. 마지막 해결책은 런타임 바이트 코드 계측을 사용하는 것이지만 완전한 JEE 환경에서 Hibernate를 JPA 공급자로 사용하는 사람들에게만 작동합니다(이 경우 "hibernate.ejb.use_class_enhancer"를 true로 설정하면 다음과 같은 작업이 수행됩니다).Entity Manager 구성) 또는 런타임 위빙을 수행하도록 구성된 스프링이 있는 최대 절전 모드를 사용합니다(일부 오래된 응용 프로그램 서버에서는 이 작업을 수행하기 어려울 수 있음).이 경우 @LazyToOne(LazyToOne옵션).NO_PROXY) 주석도 필요합니다.

자세한 내용은 다음을 참조하십시오. http://justonjava.blogspot.com/2010/09/lazy-one-to-one-and-one-to-many.html

추측일 뿐입니다. 사양을 작성하는 동안 강제로 가져오기를 수행하고 있습니다.

나는 다음과 같은 것을 기대합니다.

static Specification<AirWaybill> buildSpec() {
    return (root, query, criteriaBuilder) -> {
       Join<AirWaybill, CorporateBranch> br = (Join) root.fetch("corporateBranch");
       return criteriaBuilder.equal(br.get("addressType"), 1);
    };
}

이 경우 변경해 보십시오.root.fetchroot.join

또 다른 고려 사항은 롬복을 사용하는 동안 @Data/@Getter 주석으로 인해 불필요하게 게으른 항목이 로드된다는 것입니다.따라서 롬복을 사용할 때는 주의해야 합니다.

이건 내 사건이었어요.

검색된 데이터는 이미 게으르지만 디버거에서 데이터를 보려면 클릭할 때 디버그 모드를 사용하고 있습니다.

Jackson-datatype-hibernate를 사용하여 2단계로 이 문제를 해결할 수 있습니다.

코틀린 예

  1. 추가 위치build.gradle.kts:
implementation("com.fasterxml.jackson.datatype:jackson-datatype-hibernate5:$jacksonHibernate")
  1. 만들다@Bean
   @Bean
   fun hibernate5Module(): Module = Hibernate5Module()

주의:Module이라com.fasterxml.jackson.databind.Module,것은 아니다.java.util.Module

해결책이 있을 것 같아요.한 번 해보세요.4시간 동안 뺑소니를 치고 재판을 받은 후에 효과가 있었습니다

사용자 엔티티:

class User {
    @Id
    String id;

    @JsonManagedReference
    @OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
    private List<Address> addressDetailVOList = new ArrayList<Address>();
} 

주소 엔티티:

class Address {

    @JsonBackReference
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "userId")
    private User user;
}

부모 클래스에서 사용할 항목@JsonManagedReference그리고 아동 수업은 사용할 것입니다.@JsonBackReference이를 통해 응답 및 스택 오버플로 오류로 인한 엔터티 개체의 무한 루프를 방지할 수 있습니다.

저도 Spring data JPA와 같은 문제에 직면했습니다.아래 주석을 추가하여 주어진 ORDER ID에 대한 고객 기록을 가져올 수 있습니다.

고객 대 주문: 1 대 다

고객에 대한 주문은 게으른 부하입니다.

주문.자바

@ManyToOne(cascade = CascadeType.ALL,targetEntity = CustomerEntity.class,fetch = FetchType.LAZY)
@Fetch(FetchMode. JOIN)
@JoinColumn(name = "CUSTOMER_ID",referencedColumnName = "CUSTOMER_ID",insertable = false,updatable = false)
@LazyToOne(LazyToOneOption.PROXY)
Private CustomerEntity customer

Customer.java

@Entity
@TabLe(name = "CUSTOMER" ,
uniqueConstraints = @UniqueConstraint(columnNames= {"mobile"}))
public class CustomerEntity {

@GeneratedVaLue(strategy = GenerationType.IDENTITY)
@CoLumn(name = "customer_id" )
private Integer customerld;
private String name;
private String address;
private String city;
private String state;
private Integer zipCode;
private Integer mobileNumber;

@OneToMany(mappedBy = " customer" )
@Fetch(FetchMode.JOIN)
@LazyToOne(LazyToOneOption.PROXY)
private List<OrderEntity> orders;
}

언급URL : https://stackoverflow.com/questions/55702642/jpa-lazy-loading-is-not-working-in-spring-boot