Anonymous
Непонимание JPA FetchTypes
Сообщение
Anonymous » 13 янв 2025, 01:44
У меня есть 4 объекта:
Лицо ,
Контакт ,
Адрес и
Курс
Ниже приведена диаграмма отношений: -
Ниже приведены мои фрагменты кода:-
Классы сущностей
Код: Выделить всё
package com.anshu.example.model;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.util.HashSet;
import java.util.Set;
@Setter
@Getter
@Entity
@Table(name = "person")
public class Person extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "person_id")
private Integer personId ;
private String name ;
private int age ;
@OneToOne(fetch = FetchType.EAGER , cascade = CascadeType.ALL , targetEntity = Contact.class)
@JoinColumn(name = "contact_id" , referencedColumnName = "contact_id" , nullable = false)
private Contact contact ;
@OneToMany(mappedBy = "person" , cascade = CascadeType.ALL , fetch = FetchType.LAZY , targetEntity = Address.class)
private Set addresses = new HashSet();
@ManyToMany(mappedBy = "persons" , cascade = CascadeType.ALL , fetch = FetchType.LAZY)
private Set courses = new HashSet() ;
}
Код: Выделить всё
package com.anshu.example.model;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.util.ArrayList;
import java.util.List;
@Setter
@Getter
@Entity
public class Course extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "course_id")
private Long courseId ;
private String name ;
private float hours ;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "course_person" , joinColumns = {
@JoinColumn(name = "course_id" , referencedColumnName = "course_id")
} , inverseJoinColumns = {
@JoinColumn(name = "person_id" , referencedColumnName = "person_id")
})
private List
persons = new ArrayList() ;
}
Код: Выделить всё
package com.anshu.example.model;
import jakarta.persistence.*;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Setter
@Getter
@Entity
public class Contact extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "contact_id")
private Integer contactId ;
@Column
@NotNull
@NotBlank(message = "Name should not be blank")
private String name ;
@NotNull
@Email(message = "Email format is wrong")
@NotBlank
@Column
private String email ;
@NotBlank
@Column
private String message ;
@Enumerated(EnumType.STRING)
private Status status ;
private enum Status {
OPEN ,
CLOSED
}
}
Код: Выделить всё
package com.anshu.example.model;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Entity
@Table
@Setter
@Getter
public class Address extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer addressId ;
private String city ;
private String state ;
private String country ;
@ManyToOne(optional = false , fetch = FetchType.LAZY)
@JoinColumn(name = "person_id" , referencedColumnName = "person_id")
private Person person ;
}
Код: Выделить всё
package com.anshu.example.model;
import jakarta.persistence.Column;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import java.time.LocalDateTime;
@Getter
@Setter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity {
@Column(name = "created_at" , updatable = false)
@CreatedDate
private LocalDateTime createdAt ;
@Column(name = "created_by" , updatable = false)
@CreatedBy
private String createdBy ;
@LastModifiedDate
@Column(name = "updated_at" )
private LocalDateTime updatedAt ;
@Column(name = "updated_by" )
@LastModifiedBy
private String updatedBy ;
}
Класс обслуживания
Код: Выделить всё
package com.anshu.example.service;
import com.anshu.example.model.Address;
import com.anshu.example.model.Course;
import com.anshu.example.model.Person;
import com.anshu.example.repo.PersonRepo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
@Slf4j
@Service
public class PersonService {
private final PersonRepo personRepo ;
public PersonService(PersonRepo personRepo) {
this.personRepo = personRepo ;
}
public Person save(Person person) {
log.info(person.toString());
for(Address address : person.getAddresses()) {
address.setPerson(person);
}
for(Course course : person.getCourses()) {
course.setPersons(List.of(person));
}
Person savedPerson = personRepo.save(person) ;
removeDepth(savedPerson);
return savedPerson ;
}
public List findAll() {
List personList = personRepo.findAll() ;
// for(Person person : personList) {
// removeDepth(person);
// }
return personList ;
}
private void removeDepth(Person savedPerson) {
for(Address address : savedPerson.getAddresses()) {
address.setPerson(null);
}
for(Course course : savedPerson.getCourses()) {
course.setPersons(null);
}
}
}
Вы можете видеть, что в личном классе я пытаюсь получить только контакты с нетерпением, других я пытаюсь получить лениво.
Теперь, когда я вызываю метод службы findAll(), я должен видеть только один запрос, запущенный в моей консоли. Запрос должен получать данные о человеке и иметь соединение с таблицей контактов . Я не должен видеть никаких запросов на получение курсов и адресов, поскольку я не пытался получить их, используя какой-либо метод получения или что-то еще. Но я вижу следующее. Я ожидаю чего-то неправильного?
Код: Выделить всё
Hibernate:
select
p1_0.person_id,
p1_0.age,
p1_0.contact_id,
p1_0.created_at,
p1_0.created_by,
p1_0.name,
p1_0.updated_at,
p1_0.updated_by
from
person p1_0
Hibernate:
select
c1_0.contact_id,
c1_0.created_at,
c1_0.created_by,
c1_0.email,
c1_0.message,
c1_0.name,
c1_0.status,
c1_0.updated_at,
c1_0.updated_by
from
Contact c1_0
where
c1_0.contact_id=?
Hibernate:
select
c1_0.contact_id,
c1_0.created_at,
c1_0.created_by,
c1_0.email,
c1_0.message,
c1_0.name,
c1_0.status,
c1_0.updated_at,
c1_0.updated_by
from
Contact c1_0
where
c1_0.contact_id=?
Hibernate:
select
c1_0.contact_id,
c1_0.created_at,
c1_0.created_by,
c1_0.email,
c1_0.message,
c1_0.name,
c1_0.status,
c1_0.updated_at,
c1_0.updated_by
from
Contact c1_0
where
c1_0.contact_id=?
Hibernate:
select
c1_0.contact_id,
c1_0.created_at,
c1_0.created_by,
c1_0.email,
c1_0.message,
c1_0.name,
c1_0.status,
c1_0.updated_at,
c1_0.updated_by
from
Contact c1_0
where
c1_0.contact_id=?
Hibernate:
select
c1_0.contact_id,
c1_0.created_at,
c1_0.created_by,
c1_0.email,
c1_0.message,
c1_0.name,
c1_0.status,
c1_0.updated_at,
c1_0.updated_by
from
Contact c1_0
where
c1_0.contact_id=?
Hibernate:
select
c1_0.contact_id,
c1_0.created_at,
c1_0.created_by,
c1_0.email,
c1_0.message,
c1_0.name,
c1_0.status,
c1_0.updated_at,
c1_0.updated_by
from
Contact c1_0
where
c1_0.contact_id=?
Hibernate:
select
c1_0.contact_id,
c1_0.created_at,
c1_0.created_by,
c1_0.email,
c1_0.message,
c1_0.name,
c1_0.status,
c1_0.updated_at,
c1_0.updated_by
from
Contact c1_0
where
c1_0.contact_id=?
Hibernate:
select
c1_0.contact_id,
c1_0.created_at,
c1_0.created_by,
c1_0.email,
c1_0.message,
c1_0.name,
c1_0.status,
c1_0.updated_at,
c1_0.updated_by
from
Contact c1_0
where
c1_0.contact_id=?
Hibernate:
select
a1_0.person_id,
a1_0.addressId,
a1_0.city,
a1_0.country,
a1_0.created_at,
a1_0.created_by,
a1_0.state,
a1_0.updated_at,
a1_0.updated_by
from
Address a1_0
where
a1_0.person_id=?
2025-01-13T03:45:15.860+05:30 WARN 6840 --- [example] [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Ignoring exception, response committed already: org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Document nesting depth (1001) exceeds the maximum allowed (1000, from `StreamWriteConstraints.getMaxNestingDepth()`)
2025-01-13T03:45:15.860+05:30 WARN 6840 --- [example] [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Document nesting depth (1001) exceeds the maximum allowed (1000, from `StreamWriteConstraints.getMaxNestingDepth()`)]
Как это происходит и как это преодолеть?
Подробнее здесь:
https://stackoverflow.com/questions/793 ... erstanding
1736721879
Anonymous
У меня есть 4 объекта: [b]Лицо[/b], [b]Контакт[/b], [b]Адрес[/b] и [b]Курс[/b] Ниже приведена диаграмма отношений: - [img]https://i.sstatic.net/zw9uuj5n.png[/img] Ниже приведены мои фрагменты кода:- Классы сущностей [code]package com.anshu.example.model; import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; import lombok.ToString; import java.util.HashSet; import java.util.Set; @Setter @Getter @Entity @Table(name = "person") public class Person extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "person_id") private Integer personId ; private String name ; private int age ; @OneToOne(fetch = FetchType.EAGER , cascade = CascadeType.ALL , targetEntity = Contact.class) @JoinColumn(name = "contact_id" , referencedColumnName = "contact_id" , nullable = false) private Contact contact ; @OneToMany(mappedBy = "person" , cascade = CascadeType.ALL , fetch = FetchType.LAZY , targetEntity = Address.class) private Set addresses = new HashSet(); @ManyToMany(mappedBy = "persons" , cascade = CascadeType.ALL , fetch = FetchType.LAZY) private Set courses = new HashSet() ; } [/code] [code]package com.anshu.example.model; import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; import lombok.ToString; import java.util.ArrayList; import java.util.List; @Setter @Getter @Entity public class Course extends BaseEntity{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "course_id") private Long courseId ; private String name ; private float hours ; @ManyToMany(fetch = FetchType.LAZY) @JoinTable(name = "course_person" , joinColumns = { @JoinColumn(name = "course_id" , referencedColumnName = "course_id") } , inverseJoinColumns = { @JoinColumn(name = "person_id" , referencedColumnName = "person_id") }) private List persons = new ArrayList() ; } [/code] [code]package com.anshu.example.model; import jakarta.persistence.*; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; import lombok.ToString; @Setter @Getter @Entity public class Contact extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "contact_id") private Integer contactId ; @Column @NotNull @NotBlank(message = "Name should not be blank") private String name ; @NotNull @Email(message = "Email format is wrong") @NotBlank @Column private String email ; @NotBlank @Column private String message ; @Enumerated(EnumType.STRING) private Status status ; private enum Status { OPEN , CLOSED } } [/code] [code]package com.anshu.example.model; import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; import lombok.ToString; @Entity @Table @Setter @Getter public class Address extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer addressId ; private String city ; private String state ; private String country ; @ManyToOne(optional = false , fetch = FetchType.LAZY) @JoinColumn(name = "person_id" , referencedColumnName = "person_id") private Person person ; } [/code] [code]package com.anshu.example.model; import jakarta.persistence.Column; import jakarta.persistence.EntityListeners; import jakarta.persistence.MappedSuperclass; import lombok.Data; import lombok.Getter; import lombok.Setter; import lombok.ToString; import org.springframework.data.annotation.CreatedBy; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedBy; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import java.time.LocalDateTime; @Getter @Setter @MappedSuperclass @EntityListeners(AuditingEntityListener.class) public class BaseEntity { @Column(name = "created_at" , updatable = false) @CreatedDate private LocalDateTime createdAt ; @Column(name = "created_by" , updatable = false) @CreatedBy private String createdBy ; @LastModifiedDate @Column(name = "updated_at" ) private LocalDateTime updatedAt ; @Column(name = "updated_by" ) @LastModifiedBy private String updatedBy ; } [/code] Класс обслуживания [code]package com.anshu.example.service; import com.anshu.example.model.Address; import com.anshu.example.model.Course; import com.anshu.example.model.Person; import com.anshu.example.repo.PersonRepo; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.Arrays; import java.util.List; @Slf4j @Service public class PersonService { private final PersonRepo personRepo ; public PersonService(PersonRepo personRepo) { this.personRepo = personRepo ; } public Person save(Person person) { log.info(person.toString()); for(Address address : person.getAddresses()) { address.setPerson(person); } for(Course course : person.getCourses()) { course.setPersons(List.of(person)); } Person savedPerson = personRepo.save(person) ; removeDepth(savedPerson); return savedPerson ; } public List findAll() { List personList = personRepo.findAll() ; // for(Person person : personList) { // removeDepth(person); // } return personList ; } private void removeDepth(Person savedPerson) { for(Address address : savedPerson.getAddresses()) { address.setPerson(null); } for(Course course : savedPerson.getCourses()) { course.setPersons(null); } } } [/code] Вы можете видеть, что в личном классе я пытаюсь получить только контакты с нетерпением, других я пытаюсь получить лениво. Теперь, когда я вызываю метод службы findAll(), я должен видеть только один запрос, запущенный в моей консоли. Запрос должен получать данные о человеке и иметь соединение с таблицей контактов . Я не должен видеть никаких запросов на получение курсов и адресов, поскольку я не пытался получить их, используя какой-либо метод получения или что-то еще. Но я вижу следующее. Я ожидаю чего-то неправильного? [code]Hibernate: select p1_0.person_id, p1_0.age, p1_0.contact_id, p1_0.created_at, p1_0.created_by, p1_0.name, p1_0.updated_at, p1_0.updated_by from person p1_0 Hibernate: select c1_0.contact_id, c1_0.created_at, c1_0.created_by, c1_0.email, c1_0.message, c1_0.name, c1_0.status, c1_0.updated_at, c1_0.updated_by from Contact c1_0 where c1_0.contact_id=? Hibernate: select c1_0.contact_id, c1_0.created_at, c1_0.created_by, c1_0.email, c1_0.message, c1_0.name, c1_0.status, c1_0.updated_at, c1_0.updated_by from Contact c1_0 where c1_0.contact_id=? Hibernate: select c1_0.contact_id, c1_0.created_at, c1_0.created_by, c1_0.email, c1_0.message, c1_0.name, c1_0.status, c1_0.updated_at, c1_0.updated_by from Contact c1_0 where c1_0.contact_id=? Hibernate: select c1_0.contact_id, c1_0.created_at, c1_0.created_by, c1_0.email, c1_0.message, c1_0.name, c1_0.status, c1_0.updated_at, c1_0.updated_by from Contact c1_0 where c1_0.contact_id=? Hibernate: select c1_0.contact_id, c1_0.created_at, c1_0.created_by, c1_0.email, c1_0.message, c1_0.name, c1_0.status, c1_0.updated_at, c1_0.updated_by from Contact c1_0 where c1_0.contact_id=? Hibernate: select c1_0.contact_id, c1_0.created_at, c1_0.created_by, c1_0.email, c1_0.message, c1_0.name, c1_0.status, c1_0.updated_at, c1_0.updated_by from Contact c1_0 where c1_0.contact_id=? Hibernate: select c1_0.contact_id, c1_0.created_at, c1_0.created_by, c1_0.email, c1_0.message, c1_0.name, c1_0.status, c1_0.updated_at, c1_0.updated_by from Contact c1_0 where c1_0.contact_id=? Hibernate: select c1_0.contact_id, c1_0.created_at, c1_0.created_by, c1_0.email, c1_0.message, c1_0.name, c1_0.status, c1_0.updated_at, c1_0.updated_by from Contact c1_0 where c1_0.contact_id=? Hibernate: select a1_0.person_id, a1_0.addressId, a1_0.city, a1_0.country, a1_0.created_at, a1_0.created_by, a1_0.state, a1_0.updated_at, a1_0.updated_by from Address a1_0 where a1_0.person_id=? 2025-01-13T03:45:15.860+05:30 WARN 6840 --- [example] [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Ignoring exception, response committed already: org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Document nesting depth (1001) exceeds the maximum allowed (1000, from `StreamWriteConstraints.getMaxNestingDepth()`) 2025-01-13T03:45:15.860+05:30 WARN 6840 --- [example] [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Document nesting depth (1001) exceeds the maximum allowed (1000, from `StreamWriteConstraints.getMaxNestingDepth()`)] [/code] [b]Как это происходит и как это преодолеть?[/b] Подробнее здесь: [url]https://stackoverflow.com/questions/79350851/jpa-fetchtypes-misunderstanding[/url]