내가 일하고 SpringMVC
, Hibernate
& JSON
하지만 난이 오류를 얻고있다.
HTTP Status 500 - Could not write JSON: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationConfig.SerializationFeature.FAIL_ON_EMPTY_BEANS) )
아래 내 법인을 확인하십시오
@Entity
@Table(name="USERS")
public class User {
@Id
@GeneratedValue
@Column(name="USER_ID")
private Integer userId;
@Column(name="USER_FIRST_NAME")
private String firstName;
@Column(name="USER_LAST_NAME")
private String lastName;
@Column(name="USER_MIDDLE_NAME")
private String middleName;
@Column(name="USER_EMAIL_ID")
private String emailId;
@Column(name="USER_PHONE_NO")
private Integer phoneNo;
@Column(name="USER_PASSWORD")
private String password;
@Column(name="USER_CONF_PASSWORD")
private String confPassword;
@Transient
private String token;
@Column(name="USER_CREATED_ON")
private Date createdOn;
@OneToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL)
@Fetch(value = FetchMode.SUBSELECT)
@JoinTable(name = "USER_ROLES", joinColumns = { @JoinColumn(name = "USER_ID") }, inverseJoinColumns = { @JoinColumn(name = "ROLE_ID") })
private List<ActifioRoles> userRole = new ArrayList<ActifioRoles>();
@OneToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL,mappedBy="userDetails")
@Fetch(value = FetchMode.SUBSELECT)
private List<com.actifio.domain.Address> userAddress = new ArrayList<com.actifio.domain.Address>();
@OneToOne(cascade=CascadeType.ALL)
private Tenant tenantDetails;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmailId() {
return emailId;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getConfPassword() {
return confPassword;
}
public void setConfPassword(String confPassword) {
this.confPassword = confPassword;
}
public Date getCreatedOn() {
return createdOn;
}
public void setCreatedOn(Date createdOn) {
this.createdOn = createdOn;
}
public List<ActifioRoles> getUserRole() {
return userRole;
}
public void setUserRole(List<ActifioRoles> userRole) {
this.userRole = userRole;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public Integer getPhoneNo() {
return phoneNo;
}
public void setPhoneNo(Integer phoneNo) {
this.phoneNo = phoneNo;
}
public List<com.actifio.domain.Address> getUserAddress() {
return userAddress;
}
public void setUserAddress(List<com.actifio.domain.Address> userAddress) {
this.userAddress = userAddress;
}
public Tenant getTenantDetails() {
return tenantDetails;
}
public void setTenantDetails(Tenant tenantDetails) {
this.tenantDetails = tenantDetails;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
어떻게 해결할 수 있습니까?
답변
최대 절전 모드 프록시 개체를 통한 지연로드와 비슷한 문제가있었습니다. 지연로드 된 개인 속성이있는 클래스에 다음과 같이 주석을 추가하여 문제를 해결했습니다.
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
JSON 직렬화를 해당 주석에 중단하는 프록시 개체의 속성을 추가 할 수 있다고 가정합니다.
문제는 엔티티가 느리게로드되고 완전히로드되기 전에 직렬화가 발생한다는 것입니다.
Hibernate.initialize(<your getter method>);
답변
이것을 추가하기 위해 동일한 문제가 발생했지만 제공된 답변이 작동하지 않았습니다. 예외의 제안을 받아들이고 application.properties 파일에 추가하여 수정했습니다.
spring.jackson.serialization.fail-on-empty-beans=false
Hibernate 4.3과 함께 Spring Boot v1.3을 사용하고 있습니다.
이제 전체 개체와 중첩 된 개체를 직렬화합니다.
수정 : 2018
여전히 댓글이 있기 때문에 여기서 명확히하겠습니다. 이것은 절대적으로 오류를 숨 깁니다. 성능에 미치는 영향이 있습니다. 그 당시에는 나중에 전달하고 작업 할 무언가가 필요했습니다 (더 이상 봄을 사용하지 않고 수행했습니다). 예, 문제를 정말로 해결하고 싶다면 다른 사람의 말을 들어보세요. 지금 당장 사라지기를 원한다면이 답변을 사용하십시오. 끔찍한 생각이지만, 도대체 효과가있을 수 있습니다. 기록을 위해,이 후 다시 충돌이나 문제가 발생하지 않았습니다. 그러나 그것은 아마도 SQL 성능 악몽이 된 원인 일 것입니다.
답변
이전 답변에서 올바르게 제안했듯이 지연로드는 데이터베이스에서 개체를 가져올 때 중첩 된 개체를 가져 오지 않고 나중에 필요할 때 가져올 수 있음을 의미합니다.
이제 Jackson은 중첩 된 객체를 직렬화하려고 시도하지만 (== JSON을 생성) 일반 객체 대신 JavassistLazyInitializer를 찾으면 실패합니다. 이것은 당신이 보는 오류입니다. 이제 어떻게 해결할까요?
이전에 CP510에서 제안한대로 한 가지 옵션은 다음 구성 줄에서 오류를 억제하는 것입니다.
spring.jackson.serialization.fail-on-empty-beans=false
그러나 이것은 원인이 아니라 증상을 다루는 것입니다 . 우아하게 해결하려면 JSON에서이 객체가 필요한지 여부를 결정해야합니까?
-
JSON 형식의 개체가 필요한 경우
FetchType.LAZY
원인이되는 필드 에서 옵션을 제거합니다 (가져 오는 루트 엔터티뿐 아니라 일부 중첩 개체의 필드 일 수도 있음). -
JSON의 객체가 필요하지 않은 경우이 필드의 getter (또는 들어오는 값을 허용 할 필요가없는 경우 필드 자체)에 다음과 같이 주석을 추가합니다
@JsonIgnore
.
// this field will not be serialized to/from JSON
@JsonIgnore
private NestedType secret;
더 복잡한 요구 사항 (예 : 동일한 엔티티를 사용하는 다른 REST 컨트롤러에 대한 다른 규칙)이있는 경우 jackson 보기 또는 필터링을 사용 하거나 매우 간단한 사용 사례의 경우 중첩 된 개체를 개별적으로 가져올 수 있습니다.
답변
Hibernate lazy-loading을 처리하는 Jackson 용 애드온 모듈을 사용할 수 있습니다.
https://github.com/FasterXML/jackson-datatype-hibernate에 대한 자세한 정보는 최대 절전 모드 3과 4를 별도로 지원합니다.
답변
문제는 엔티티를 검색하는 방식이라고 생각합니다.
아마도 다음과 같이 할 수 있습니다.
Person p = (Person) session.load(Person.class, new Integer(id));
get
대신 방법을 사용해보십시오.load
Person p = (Person) session.get(Person.class, new Integer(id));
문제는로드 방법을 사용하면 실제 객체가 아닌 프록시 만 얻을 수 있다는 것입니다. 프록시 개체에는 속성이 이미로드되어 있지 않으므로 직렬화가 발생하면 직렬화 할 속성이 없습니다. get 메서드를 사용하면 실제로 실제 개체를 얻을 수 있으며이 개체는 실제로 직렬화 될 수 있습니다.
답변
그것은 나를 위해 작동합니다
@JsonIgnoreProperties({"hibernateLazyInitializer","handler"})
예 :
@Entity
@Table(name = "user")
@Data
@NoArgsConstructor
@JsonIgnoreProperties({"hibernateLazyInitializer","handler"})
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Date created;
}
답변
문제를 해결하는 방법에는 두 가지가 있습니다.
방법 1 :
추가
spring.jackson.serialization.fail-on-empty-beans=false
로 application.properties
방법 2 :
join fetch
JPQL 쿼리에서 사용 하여 상위 개체 데이터를 검색합니다. 아래를 참조하세요.
@Query(value = "select child from Child child join fetch child.parent Parent ",
countQuery = "select count(*) from Child child join child.parent parent ")
public Page<Parent> findAll(Pageable pageable);