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 속성이 로드됩니다.아래 이미지를 참조하십시오.
내 질문 중 하나는 잭슨이 그런 행동에 관여할 수 있을까 하는 것입니다.게으른 로딩을 활성화하기 위해 제가 놓쳤을 수 있는 방법이 있습니까?
편집
또 다른 질문은 디버거가 게으른 로딩을 망치는 데 관여할 수 있는가 하는 것입니다.
편집 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를 사용하도록 강제하는 방법은 몇 가지 옵션이 있습니다.
- 가장 간단한 것은 일대일 관계를 가장하는 것입니다.수집을 느리게 로드하는 것이 단일 null 가능한 속성을 느리게 로드하는 것보다 훨씬 쉬우므로 이 방법은 작동하지만 일반적으로 복잡한 JPQL/HQL 쿼리를 사용하는 경우에는 매우 불편합니다.
- 다른 하나는 빌드 시간 바이트 코드 계측을 사용하는 것입니다.자세한 내용은 최대 절전 모드 설명서 19.1.7을 참조하십시오.게으른 속성 가져오기를 사용합니다.이 경우 @LazyToOne(LazyToOneOption)을 추가해야 합니다.NO_PROXY) 주석을 일대일 관계에 추가하여 게으르게 만듭니다.가져오기를 LAY로 설정하는 것만으로는 충분하지 않습니다.
- 마지막 해결책은 런타임 바이트 코드 계측을 사용하는 것이지만 완전한 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.fetch
root.join
또 다른 고려 사항은 롬복을 사용하는 동안 @Data/@Getter 주석으로 인해 불필요하게 게으른 항목이 로드된다는 것입니다.따라서 롬복을 사용할 때는 주의해야 합니다.
이건 내 사건이었어요.
검색된 데이터는 이미 게으르지만 디버거에서 데이터를 보려면 클릭할 때 디버그 모드를 사용하고 있습니다.
Jackson-datatype-hibernate를 사용하여 2단계로 이 문제를 해결할 수 있습니다.
코틀린 예
- 추가 위치
build.gradle.kts
:
implementation("com.fasterxml.jackson.datatype:jackson-datatype-hibernate5:$jacksonHibernate")
- 만들다
@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
'programing' 카테고리의 다른 글
실제 쿼리를 실행하지 않고 JDBC 문에 대한 SQL 구문을 확인하려면 어떻게 해야 합니까? (0) | 2023.07.21 |
---|---|
최대 절전 모드(EntityManager) 또는 JPA를 사용하여 Oracle 함수 또는 프로시저를 호출하는 방법 (0) | 2023.07.21 |
테이블의 그룹화된 레코드별 실행 총계 (0) | 2023.07.21 |
오라클 임시 테이블에 인덱스를 올려도 안전합니까? (0) | 2023.07.21 |
일정한 시간이 지난 후에 중단되는 경우 Spring Scheduled 실행 중지 (0) | 2023.07.21 |