programing

클래스 org.hibernate.proxy.pojo.javassist의 시리얼라이저를 찾을 수 없습니다.자바시스트?

minxs 2023. 3. 7. 22:00
반응형

클래스 org.hibernate.proxy.pojo.javassist의 시리얼라이저를 찾을 수 없습니다.자바시스트?

작업 중입니다.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;
    }

    }

이 문제를 해결하려면 어떻게 해야 하나요?

hibernate 프록시 오브젝트를 통한 로딩이 느릴 때도 같은 문제가 있었습니다.개인 속성을 느리게 로드한 클래스에 주석을 달아 문제를 해결했습니다.

@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})

프록시 오브젝트의 속성을 추가하여 JSON의 시리얼화를 중단시킬 수 있습니다.

문제는 엔티티가 느릿느릿 로드되고 완전히 로드되기 전에 직렬화가 이루어진다는 것입니다.

Hibernate.initialize(<your getter method>);

덧붙이자면, 같은 문제에 부딪혔는데, 제공된 답변이 작동하지 않았습니다.예외의 제안을 받아들여 application.properties 파일에 추가하여 수정했습니다.

spring.jackson.serialization.fail-on-empty-beans=false

Spring Boot v1.3과 하이버네이트 4.3을 사용하고 있습니다.

이제 전체 개체와 중첩된 개체를 일련화합니다.

편집: 2018년

아직 댓글이 올라오고 있기 때문에 여기서 설명하겠습니다.이렇게 하면 오류만 완전히 숨겨집니다.퍼포먼스에 대한 영향이 있습니다.그 때, 나는 그것을 전달하고 나중에 작업할 것이 필요했습니다(스프링을 사용하지 않기 때문에).그래서, 만약 당신이 이 문제를 정말로 해결하고 싶다면, 다른 사람의 말을 들어라.만약 당신이 일단 그것을 없애고 싶다면, 이 답을 사용하세요.끔찍한 생각이긴 하지만 너한테는 먹힐지도 몰라참고로, 이 사건 이후로 다시는 충돌이나 문제가 발생하지 않았습니다.그러나 이것이 SQL 성능의 악몽이 되는 원인일 것입니다.

이전 답변에서 올바르게 제시되었듯이 느린 로딩은 데이터베이스에서 개체를 가져올 때 중첩된 개체가 가져오지 않고 나중에 필요할 때 가져올 수 있음을 의미합니다.

이제 Jackson은 중첩된 개체를 직렬화하려고 시도하지만(==에서 JSON을 사용), JavassistLazy를 찾아서 실패합니다.일반 객체가 아닌 이니셜라이저.이것이 표시되는 에러입니다.자, 어떻게 해결할까요?

앞서 CP510에서 권장한 바와 같이 다음 구성 행에 의해 오류를 억제하는 방법이 있습니다.

spring.jackson.serialization.fail-on-empty-beans=false

하지만 이건 증상을 다루는 거지 원인이 아니라우아하게 해결하려면 JSON에서 이 오브젝트가 필요한지 아닌지를 결정해야 합니다.

  1. JSON을 합니다.FetchType.LAZY옵션(가져오는 루트 엔티티뿐만 아니라 중첩된 일부 개체의 필드일 수도 있음)을 선택합니다.

  2. 이 자체에 JSON을 사용하여 .@JsonIgnore를 들면, '아까다'와 같이요

    // this field will not be serialized to/from JSON @JsonIgnore private NestedType secret;

더 복잡한 요구(예: 동일한 엔티티를 사용하는 REST 컨트롤러마다 다른 규칙)가 있는 경우 잭슨또는 필터링을 사용하거나 매우 단순한 사용 사례를 위해 중첩된 개체를 개별적으로 가져올 수 있습니다.

휴지 상태 지연 로드를 처리하는 잭슨용 애드온 모듈을 사용할 수 있습니다.

hibernate 3과 hibernate 4를 개별적으로 지원하는 https://github.com/FasterXML/jackson-datatype-hibernate에 대한 자세한 내용은 다음과 같습니다.

문제는 엔티티를 회수하는 방법이라고 생각합니다.

다음과 같은 작업을 수행할 수 있습니다.

Person p = (Person) session.load(Person.class, new Integer(id));

해 보세요.getload

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=falseapplication.properties로 이동합니다.

방법 2:

join fetchJPQL 쿼리에서 상위 개체 데이터를 가져오려면 다음을 참조하십시오.

@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); 

이 주석을 엔티티 클래스(모델)에 추가하면 휴지 상태 프록시 개체를 통해 로드 속도가 느려집니다.

@Json Ignore Properties({"hibernate Lazy")이니셜라이저", "핸들러"}

이 예외

org.springframework.springframework.cHttp Message Not Writable예외.

serializable object(직렬화 가능 객체)
이것은 봄에 발생하는 문제입니다.이 문제를 해결하려면 응답 출력으로 POJO 개체를 보냅니다.

예:

    @Entity
    @Table(name="user_details")
    public class User implements Serializable{

        @Id
        @GeneratedValue(strategy= GenerationType.IDENTITY)
        @Column(name="id")
        private Integer id;

        @Column(name="user_name")
        private String userName;

        @Column(name="email_id")
        private String emailId;

        @Column(name="phone_no")
        private String phone;

//setter and getters

POJO 클래스:

public class UserVO {

    private int Id;
    private String userName;
    private String emailId;
    private String phone;
    private Integer active;

//setter and getters

컨트롤러에서는 serilizable 객체필드를 POJO 클래스필드로 변환하여 출력으로 pojo 클래스를 반환합니다.

         User u= userService.getdetials(); // get data from database

        UserVO userVo= new UserVO();  // created pojo class object

        userVo.setId(u.getId());
        userVo.setEmailId(u.getEmailId());
        userVo.setActive(u.getActive());
        userVo.setPhone(u.getPhone());
        userVo.setUserName(u.getUserName());
       retunr userVo;  //finally send pojo object as output.

Hibernate 5.2 이상에서는 다음과 같이 hibernate 프록시를 삭제할 수 있습니다.실제 오브젝트가 표시되어 올바르게 시리얼화할 수 있습니다.

Object unproxiedEntity = Hibernate.unproxy( proxy );

휴지 상태에서는 잭슨 데이터형 휴지 상태 프로젝트를 사용하여 느리게 로드된 개체와의 JSON 직렬화/비직렬화를 수용할 수 있습니다.

예를들면,

import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JacksonDatatypeHibernate5Configuration {

    // Register Jackson Hibernate5 Module to handle JSON serialization of lazy-loaded entities
    // Any beans of type com.fasterxml.jackson.databind.Module are automatically
    // registered with the auto-configured Jackson2ObjectMapperBuilder
    // https://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html#howto-customize-the-jackson-objectmapper
    @Bean
    public Module hibernate5Module() {
        Hibernate5Module hibernate5Module = new Hibernate5Module();
        hibernate5Module.enable( Hibernate5Module.Feature.FORCE_LAZY_LOADING );
        hibernate5Module.disable( Hibernate5Module.Feature.USE_TRANSIENT_ANNOTATION );
        return hibernate5Module;
    }
}

이 솔루션은 @marco의 다음 솔루션에서 영감을 얻었습니다.나는 또한 이 데이터로 그의 답변을 업데이트했다.

여기서의 문제는 하위 오브젝트의 느린 로딩에 관한 것입니다.잭슨은 풀 블로우된 오브젝트가 아닌 휴지 상태의 프록시만 찾습니다.

따라서 두 가지 옵션이 남아 있습니다.여기서 대부분의 투표된 답변에서와 같이 예외를 억제하거나 LazyLoad 개체가 로드되었는지 확인합니다.

후자의 옵션을 선택할 경우 해결 방법은 잭슨 데이터형 라이브러리를 사용하여 시리얼라이제이션 전에 지연 부하 의존관계를 초기화하도록 라이브러리를 구성하는 것입니다.

이를 위해 새로운 설정 클래스를 추가했습니다.

@Configuration
public class JacksonConfig extends WebMvcConfigurerAdapter {

@Bean
@Primary
public MappingJackson2HttpMessageConverter jacksonMessageConverter(){
    MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
    ObjectMapper mapper = new ObjectMapper();
    Hibernate5Module module = new Hibernate5Module();
    module.enable(Hibernate5Module.Feature.FORCE_LAZY_LOADING);
    mapper.registerModule(module);
    messageConverter.setObjectMapper(mapper);
    return messageConverter;
}

}

@Primary다른 콩의 초기화에 다른 잭슨 설정이 사용되고 있지 않은 것을 확인합니다. @Bean평소와 다름없다. module.enable(Hibernate5Module.Feature.FORCE_LAZY_LOADING);의존관계 Lazy 로드를 유효하게 하는 것입니다.

주의 - 성능에 영향을 줄 수 있는지 확인하십시오. 때로는 OVER 가져오기가 도움이 될 수 있습니다. 그러나 급하게 가져오더라도 이 코드가 계속 필요합니다. 프록시 개체는 다음을 제외한 다른 모든 매핑에 여전히 존재하기 때문입니다.@OneToOne

PS: 일반적인 코멘트로서 Json 응답으로 데이터 오브젝트 전체를 송신하는 것은 권장하지 않습니다.이 통신에는 Dto를 사용하고 맵 구조 등의 맵을 사용해야 합니다.이것에 의해, 우발적인 시큐러티의 허점이나 예외로부터 해방됩니다.

저도 지금 같은 문제가 있어요.@json을 사용하여 가져오기 작업을 수정했는지 확인합니다.IQgnore

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="teachers")
@JsonIgnoreProperties("course")
Teacher teach;

"(complete=...)를 삭제하기만 하면 됩니다.)" 또는 "@jsonIgnore"라는 주석을 붙이면 동작합니다.

@ManyToOne
@JoinColumn(name="teachers")
@JsonIgnoreProperties("course")
Teacher teach;

또는 다음과 같이 매퍼를 설정할 수 있습니다.

// 느린 로드를 위한 커스텀 구성

public static class HibernateLazyInitializerSerializer extends JsonSerializer<JavassistLazyInitializer> {

    @Override
    public void serialize(JavassistLazyInitializer initializer, JsonGenerator jsonGenerator,
            SerializerProvider serializerProvider)
            throws IOException, JsonProcessingException {
        jsonGenerator.writeNull();
    }
}

및 매퍼를 설정합니다.

    mapper = new JacksonMapper();
    SimpleModule simpleModule = new SimpleModule(
            "SimpleModule", new Version(1,0,0,null)
    );
    simpleModule.addSerializer(
            JavassistLazyInitializer.class,
            new HibernateLazyInitializerSerializer()
    );
    mapper.registerModule(simpleModule);

문제의 원인은 휴지 상태 엔티티 관계일 수 있습니다.그냥 관련 실체의 게으른 로딩만 멈추면...예를 들어...customer Type에 lazy="false"를 설정하여 아래 문제를 해결했습니다.

<class name="Customer" table="CUSTOMER">
        <id name="custId" type="long">
            <column name="CUSTID" />
            <generator class="assigned" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="phone" type="java.lang.String">
            <column name="PHONE" />
        </property>
        <property name="pan" type="java.lang.String">
            <column name="PAN" />
        </property>

        <many-to-one name="customerType" not-null="true" lazy="false"></many-to-one>
    </class>
</hibernate-mapping>

변경했습니다(주석 모델 클래스에서)

fetch = FetchType입니다.게으른

로.

fetch = FetchType입니다.열심

일을 예쁘게 해서...

참 좋다.

잭슨과 관련된 문제입니다.이를 방지하려면 잭슨에게 중첩된 관계 또는 중첩된 클래스를 직렬화하지 않도록 지시하십시오.

다음 예를 참조하십시오.City, State Country 클래스에 매핑된 주소 클래스와 State 자체는 Country 및 Country를 가리키고 있습니다.Spring boot REST API를 통해 주소 값을 가져오면 위의 오류가 발생합니다.이를 방지하려면 매핑클래스(레벨1 JSON을 반영)를 시리얼화하고, 네스트된 관계를 무시합니다.@JsonIgnoreProperties(value = {"state"}) ,@JsonIgnoreProperties(value = {"country"}) ★★★★★★★★★★★★★★★★★」@JsonIgnoreProperties(value = {"region"})

그러면 위의 오류와 함께 Lazeload 예외가 방지됩니다.아래 코드를 예로 들어 모델 클래스를 변경하십시오.

Address.java

@Entity
public class Address extends AbstractAuditingEntity
{
    private static final long serialVersionUID = 4203344613880544060L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "street_name")
    private String streetName;

    @Column(name = "apartment")
    private String apartment;

    @ManyToOne
    @JoinColumn(name = "city_id")
    @JsonIgnoreProperties(value = {"state"})
    private City city;

    @ManyToOne
    @JoinColumn(name = "state_id")
    @JsonIgnoreProperties(value = {"country"})
    private State state;

    @ManyToOne
    @JoinColumn(name = "country_id")
    @JsonIgnoreProperties(value = {"region"})
    private Country country;

    @ManyToOne
    @JoinColumn(name = "region_id")
    private Region region;

    @Column(name = "zip_code")
    private String zipCode;

    @ManyToOne
    @JoinColumn(name = "address_type_id", referencedColumnName = "id")
    private AddressType addressType;

}

City.java

@EqualsAndHashCode(callSuper = true)
@Entity
@Table(name = "city")
@Cache(region = "cityCache",usage = CacheConcurrencyStrategy.READ_WRITE)
@Data
public class City extends AbstractAuditingEntity
{
    private static final long serialVersionUID = -8825045541258851493L;

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    //@Length(max = 100,min = 2)
    private String name;


    @ManyToOne
    @JoinColumn(name = "state_id")
    private State state;
}

State.java

@Entity
@Table(name = "state")
@Data
@EqualsAndHashCode(callSuper = true)
public class State extends AbstractAuditingEntity
{
    private static final long serialVersionUID = 5553856435782266275L;

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "code")
    private String code;

    @Column(name = "name")
    @Length(max = 200, min = 2)
    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "country_id")
    private Country country;

}

Country.java

@Entity
@Table(name = "country")
@Data
@EqualsAndHashCode(callSuper = true)
public class Country extends AbstractAuditingEntity
{
    private static final long serialVersionUID = 6396100319470393108L;

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    @Length(max = 200, min = 2)
    private String name;

    @Column(name = "code")
    @Length(max = 3, min = 2)
    private String code;

    @Column(name = "iso_code")
    @Length(max = 3, min = 2)
    private String isoCode;

    @ManyToOne
    @JoinColumn(name = "region_id")
    private Region region;
}

@Json Ignore Properties({"hibernate Lazy")이니셜라이저", 핸들러"}

나에겐 효과가 있어

해라

implements interface Serializable

언급URL : https://stackoverflow.com/questions/24994440/no-serializer-found-for-class-org-hibernate-proxy-pojo-javassist-javassist

반응형