Không tìm thấy trình tuần tự nào cho lớp org.hibernate.proxy.pojo.javassist.Javassist?


94

Tôi đang làm việc SpringMVC, Hibernate& JSONnhưng tôi gặp lỗi này.

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

Vui lòng kiểm tra Thực thể của tôi bên dưới

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

    }

Làm sao tôi có thể giải quyết việc này?


Hãy thể hiện stacktrace và mã nơi ngoại lệ xảy ra
geoand

Nếu không có bất kỳ kiến ​​thức nào về những gì mã của bạn đang cố gắng thực hiện, sẽ có một chút khó khăn để gỡ lỗi, nhưng có thể bạn sẽ muốn kiểm tra github.com/FasterXML/jackson-datatype-hibernate vì bạn đang sử dụng Jackson và Hibernate
geoand

Bạn đang cố tạo JSON từ lớp này? Trong trường hợp này, trình tuần tự JSON cố gắng viết tất cả các thuộc tính, cũng là HashSet của các mối quan hệ nhiều-nhiều của bạn; điều này làm cho một initializer ngoại lệ lười biếng
Angelo Immediata

bạn có thể tìm thấy câu hỏi tương tự tại stackoverflow.com/questions/4362104/…
Matrix Buster,

@ user2963481 ... Câu hỏi hay và rất hữu ích đấy anh em.
Brain

Câu trả lời:


192

Tôi đã gặp sự cố tương tự với tải chậm qua đối tượng proxy ngủ đông. Giải quyết vấn đề này bằng cách chú thích lớp có các thuộc tính riêng tư được tải chậm với:

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

Tôi giả sử bạn có thể thêm các thuộc tính trên đối tượng proxy của mình để phá vỡ tuần tự hóa JSON cho chú thích đó.

Vấn đề là các thực thể được tải một cách lười biếng và quá trình tuần tự hóa xảy ra trước khi chúng được tải đầy đủ.

Hibernate.initialize(<your getter method>);

3
Nó cũng làm việc cho tôi ... Có lời giải thích nào cho hành vi kỳ lạ này không?
Victor

7
@ ankur-singhal bạn nên nhấn mạnh rằng chú thích này là cần thiết trên lớp lồng nhau chứ KHÔNG phải lớp gọi.
Darwayne

1
Yahooo ... nó hoạt động. Tôi đã thử vài lần và làm việc. Tôi đã thử một vài cách và BoooM. Đã làm việc.
Brain

2
Cảm ơn đã làm việc cho tôi quá. Bạn cần thêm chú thích này vào các thực thể truy cập các thực thể khác có các bean tải chậm.
Shafqat Shafi,

3
Tôi nghĩ rằng đây không phải là một giải pháp đúng cho vấn đề. Khi chúng tôi tuần tự hóa, chúng tôi mong đợi subobject hoàn chỉnh hoặc ít nhất là khóa chính của đối tượng phụ sẽ được trả lại trong kết quả. Việc thêm các chú thích này sẽ chỉ loại bỏ lỗi, nhưng sẽ không cung cấp cho bạn kết quả mong muốn.
Anand Vaidya,

84

Chỉ cần thêm điều này vào, tôi đã gặp phải vấn đề tương tự, nhưng các câu trả lời được cung cấp không hoạt động. Tôi đã sửa nó bằng cách lấy đề xuất của ngoại lệ và thêm vào tệp application.properties ...

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

Tôi đang sử dụng Spring Boot v1.3 với Hibernate 4.3

Bây giờ nó tuần tự hóa toàn bộ đối tượng và các đối tượng lồng nhau.

CHỈNH SỬA: 2018

Vì điều này vẫn còn nhận xét, tôi sẽ làm rõ ở đây. Điều này hoàn toàn chỉ ẩn lỗi. Các tác động hiệu suất là ở đó. Vào thời điểm đó, tôi cần một thứ gì đó để giao và làm việc đó sau (điều mà tôi đã làm thông qua việc không sử dụng mùa xuân nữa). Vì vậy, có, hãy lắng nghe người khác nếu bạn thực sự muốn giải quyết vấn đề. Nếu bạn chỉ muốn nó biến mất ngay bây giờ, hãy tiếp tục và sử dụng câu trả lời này. Đó là một ý tưởng khủng khiếp, nhưng thật tệ, có thể hiệu quả với bạn. Đối với hồ sơ, không bao giờ có sự cố hoặc sự cố nữa sau đó. Nhưng nó có thể là nguồn gốc của những gì cuối cùng trở thành một cơn ác mộng về hiệu suất SQL.


8
Giải quyết vấn đề nhưng json sẽ chứa hai thuộc tính không cần thiết thêm"handler":{},"hibernateLazyInitializer":{}
prettyvoid

tuyệt quá! cố định ở đây cũng vậy, đây là câu trả lời
Hinotori

@prettyvoid Tại sao các thuộc tính bổ sung đó lại tồn tại?
Robert Moon

12
@RobertMoon Nếu bạn muốn để có được loại bỏ chúng, bạn có thể chú thích thực thể của bạn với@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
prettyvoid

@prettyvoid Cảm ơn. Tôi tìm thấy một giải pháp khác là thay đổi LAZY thành EAGER. Nó có ảnh hưởng đến hiệu suất không?
Robert Moon

69

Như được đề xuất chính xác trong các câu trả lời trước, tải chậm có nghĩa là khi bạn tìm nạp đối tượng của mình từ cơ sở dữ liệu, các đối tượng lồng nhau sẽ không được tìm nạp (và có thể được tìm nạp sau khi được yêu cầu).

Bây giờ Jackson cố gắng tuần tự hóa đối tượng lồng nhau (== tạo JSON khỏi nó), nhưng không thành công khi nó tìm thấy JavassistLazyInitializer thay vì đối tượng bình thường. Đây là lỗi bạn thấy. Bây giờ, làm thế nào để giải quyết nó?

Như được đề xuất bởi CP510 trước đây, một tùy chọn là loại bỏ lỗi bằng dòng cấu hình này:

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

Nhưng điều này là giải quyết các triệu chứng, không phải nguyên nhân . Để giải quyết nó một cách thanh lịch, bạn cần quyết định xem bạn có cần đối tượng này trong JSON hay không?

  1. Nếu bạn cần đối tượng trong JSON, hãy xóa FetchType.LAZYtùy chọn khỏi trường gây ra nó (nó cũng có thể là một trường trong một số đối tượng lồng nhau, không chỉ trong thực thể gốc mà bạn đang tìm nạp).

  2. Nếu không cần đối tượng trong JSON, hãy chú thích getter của trường này (hoặc chính trường này, nếu bạn cũng không cần chấp nhận các giá trị đến) @JsonIgnore, ví dụ:

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

Nếu bạn có nhu cầu phức tạp hơn (ví dụ: các quy tắc khác nhau cho các bộ điều khiển REST khác nhau sử dụng cùng một thực thể), bạn có thể sử dụng chế độ xem hoặc bộ lọc jackson hoặc đối với trường hợp sử dụng rất đơn giản, tìm nạp các đối tượng lồng nhau một cách riêng biệt.


16
Đây là câu trả lời tốt nhất. Giải quyết gốc rễ của vấn đề, không chỉ che dấu các triệu chứng cho các lập trình viên tiếp theo phải giải quyết.
Andrew

2
Bạn là người hùng của tôi.
Lay Leangsros

cảm ơn bạn rất nhiều vì đã giải thích lý do đằng sau lỗi và cung cấp hai giải pháp phù hợp
Mauricio Poppe

Cảm ơn vì điều này, tuy nhiên tôi thấy springfox-swagger vẫn cho tôi lỗiRangeError: Maximum call stack size exceeded
Pra_A

18

Bạn có thể sử dụng mô-đun bổ trợ cho Jackson để xử lý tải chậm Hibernate.

Thông tin thêm về https://github.com/FasterXML/jackson-datatype-hibernate wich hỗ trợ hibernate 3 và 4 riêng biệt.


7
Đây thực sự phải là câu trả lời chính xác. Tất cả các câu trả lời khác đang che giấu vấn đề hơn là giải quyết nó.
Ahmed Hassanien

Nhưng làm thế nào để sử dụng mô-đun này? có bất kỳ hướng dẫn cho nó?
Anand Vaidya

Cách định cấu hình jackson-datatype-hibernate: stackoverflow.com/q/33727017
Chase

13

Tôi nghĩ rằng vấn đề là cách bạn truy xuất thực thể.

Có thể bạn đang làm điều gì đó như thế này:

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

Hãy thử sử dụng phương pháp getthay vìload

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

Vấn đề là với phương thức tải, bạn chỉ nhận được một proxy chứ không phải đối tượng thực. Đối tượng proxy không có các thuộc tính đã được tải nên khi tuần tự hóa xảy ra, không có thuộc tính nào được tuần tự hóa. Với phương thức get, bạn thực sự nhận được đối tượng thực, đối tượng này trên thực tế có thể được tuần tự hóa.


2
Một lỗi tương tự đã xảy ra với tôi khi tôi sử dụng getOne thay vì findOne. Trong trường hợp của tôi, kho giao diện của tôi đang mở rộng JpaRepository. findOne làm việc tốt mà không cần bất kỳ chú thích Json hoặc thay đổi trong application.properties
James Freitas

Giống như James Freitas, tôi cũng phát hiện ra rằng getOne dẫn đến vấn đề này, và sử dụng thay vào đó, ví dụ, findById -solved vấn đề mà không cần phải sử dụng chú thích hoặc trên đường được đưa ra trong các thuộc tính ứng dụng
MY

1
Người bạn cùng làm việc của tôi đã giải thích cho tôi và nói với tôi rằng: "Sự khác biệt cơ bản là getOne được tải chậm còn findOne thì không" - có nghĩa là rõ ràng người đó không thực sự lấy các hàng dữ liệu từ db mà chỉ tạo ra các tham chiếu. Sau đó, thay vì nhận được hàng trên thực tế, đó là trường hợp thường là mong muốn
MY

@JamesFreitas CÓ! Cảm ơn bạn! Và cảm ơn Carlos đã dẫn dắt James đến kết luận tốt đẹp này!
Filip Savic

9

nó làm việc cho tôi

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

ví dụ

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

}

5

Có hai cách để khắc phục sự cố.

Cách 1 :

Thêm spring.jackson.serialization.fail-on-empty-beans=falsevào application.properties

Cách 2 :

Sử dụng join fetchtrong truy vấn JPQL để truy xuất dữ liệu đối tượng mẹ, xem bên dưới:

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

Cảm ơn! Giải pháp đầu tiên thật tuyệt vời!
Lucas Moyano Angelini

Cách 1. Tuyệt vời. Cảm ơn bạn.
Lay Leangsros

3

Thêm Chú thích này vào Lớp thực thể (Mô hình) phù hợp với tôi, điều này gây ra tải chậm qua đối tượng proxy ngủ đông.

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


2

Ngoại lệ này

org.springframework.http.converter.HttpMessageNotWoritesException

nhận được bởi vì, tôi hy vọng như vậy, đầu ra phản hồi của bạn đang gửi dưới dạng đối tượng Serializable.
Đây là vấn đề xảy ra vào mùa xuân. Để giải quyết vấn đề này, hãy gửi đối tượng POJO làm đầu ra phản hồi.

Thí dụ :

    @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

Lớp POJO:

public class UserVO {

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

//setter and getters

Trong bộ điều khiển chuyển đổi các trường đối tượng có thể phân loại thành các trường lớp POJO và trả về lớp pojo dưới dạng đầu ra.

         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.

Có, tôi đang làm việc như nhau, nhưng thậm chí làm cùng tôi nhận được lỗi tương tự, bởi vì tôi đang gửi đối tượng liên quan đến dữ liệu đó là gì, nhưng thiết lập các lớp Entity
Pra_A

2

Trong Hibernate 5.2 trở lên, bạn có thể xóa proxy ngủ đông như bên dưới, nó sẽ cung cấp cho bạn đối tượng thực tế để bạn có thể tuần tự hóa nó đúng cách:

Object unproxiedEntity = Hibernate.unproxy( proxy );

nó cũng sẽ tự động gọi Hibernate.initializetrước.
GMsoF

@Tim, nó nên được thêm vào trước tuần tự hóa json. Sự cố xảy ra do có đối tượng proxy ngủ đông được tìm thấy trong quá trình tuần tự hóa, vì vậy sau khi loại bỏ nó, quá trình tuần tự hóa sẽ ổn. Nếu bạn đang sử dụng bộ điều khiển lò xo, thì bạn phải làm điều đó trước khi bộ điều khiển kết thúc.
GMsoF

1

Đối với Hibernate, bạn có thể sử dụng dự án jackson-datatype-hibernate để phù hợp với tuần tự hóa / giải mã JSON với các đối tượng được tải lười biếng.

Ví dụ,

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;
    }
}

Nếu tôi sử dụng cái này thì tôi nhận được can't parse JSON. Raw result:. Bất kỳ giúp đỡ?
Pra_A

1

Giải pháp được lấy cảm hứng từ giải pháp dưới đây của @marco. Tôi cũng đã cập nhật câu trả lời của anh ấy với những dữ liệu này.

Vấn đề ở đây là về việc tải chậm các đối tượng con, nơi Jackson chỉ tìm thấy các proxy ngủ đông, thay vì các đối tượng được thổi đầy đủ.

Vì vậy, chúng tôi còn lại với hai tùy chọn - Loại bỏ ngoại lệ, giống như đã thực hiện ở trên trong hầu hết các câu trả lời được bình chọn ở đây hoặc đảm bảo rằng các đối tượng LazyLoad được tải.

Nếu bạn chọn đi với tùy chọn sau, giải pháp sẽ là sử dụng thư viện jackson-datatype và định cấu hình thư viện để khởi tạo các phụ thuộc lazy-load trước khi tuần tự hóa.

Tôi đã thêm một lớp cấu hình mới để làm điều đó.

@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đảm bảo rằng không có cấu hình Jackson nào khác được sử dụng để khởi tạo bất kỳ bean nào khác. @Beanlà như thường lệ. module.enable(Hibernate5Module.Feature.FORCE_LAZY_LOADING);là cho phép tải Lazy các phụ thuộc.

Thận trọng - Vui lòng xem tác động đến hiệu suất của nó. đôi khi tìm nạp EAGER hữu ích, nhưng ngay cả khi bạn làm cho nó háo hức, bạn vẫn cần mã này, vì các đối tượng proxy vẫn tồn tại cho tất cả các Ánh xạ khác ngoại trừ@OneToOne

Tái bút: Theo nhận xét chung, tôi không khuyến khích thực hành gửi toàn bộ đối tượng dữ liệu trở lại trong phản hồi Json, Người ta nên sử dụng Dto cho giao tiếp này và sử dụng một số trình liên kết như mapstruct để ánh xạ chúng. Điều này giúp bạn tránh khỏi những sơ hở bảo mật ngẫu nhiên, cũng như ngoại lệ ở trên.


1

Tôi đang gặp vấn đề tương tự ngay bây giờ. kiểm tra xem bạn có sửa lỗi tìm nạp trong lười biếng không với @jsonIQgnore

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

Chỉ cần xóa "(fetch = ...)" hoặc chú thích "@jsonIgnore" và nó sẽ hoạt động

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

0

Hoặc bạn có thể định cấu hình trình liên kết dưới dạng:

// cấu hình tùy chỉnh để tải chậm

public static class HibernateLazyInitializerSerializer extends JsonSerializer<JavassistLazyInitializer> {

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

và định cấu hình trình liên kết:

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

0

Đó có thể là mối quan hệ thực thể Hibernate của bạn gây ra sự cố ... chỉ cần dừng tải chậm đối với thực thể có liên quan đó ... ví dụ: tôi đã giải quyết bên dưới bằng cách đặt lazy = "false" cho customerType.

<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>

1
xin vui lòng thông báo trong bài đăng của bạn rằng nó có thể là giải pháp rất nguy hiểm trong ứng dụng đời thực.
panurg

0

Tôi đã thay đổi (trong lớp mô hình Chú thích)

fetch = FetchType.LAZY

đến

fetch = FetchType.EAGER

và hoạt động theo cách khá ...

Yêu nó.


5
Trong khi điều này giải quyết được vấn đề thì nó rất nguy hiểm. Thay đổi fetchchiến lược trên một mô hình có một số hậu quả về hiệu suất. Với thay đổi này, bạn đang mang lại nhiều dữ liệu hơn từ cơ sở dữ liệu. Nó có thể là một giải pháp hợp lệ, nhưng trước tiên cần phải nghiên cứu hiệu suất.
João Menighin

1
Nếu bạn biết mình là người mẫu và không có nhiều thực thể liên quan, bạn có thể dành một chút chi phí và năng lực để có được một thực thể đầy đủ. nhưng là tốt để biết rằng luôn luôn là tốt nhất mà bạn sử dụng LAZY lấy
Sham Fiorin

0

Đây là một vấn đề với Jackson. Để ngăn chặn điều này, hãy hướng dẫn Jackson không tuần tự hóa mối quan hệ lồng nhau hoặc lớp lồng nhau.

Hãy xem ví dụ sau. Lớp địa chỉ được ánh xạ tới các lớp Thành phố , Tiểu bangQuốc gia và chính Tiểu bang đang trỏ đến Quốc gia và Quốc gia trỏ đến Vùng. Khi nhận các giá trị địa chỉ của bạn thông qua API REST khởi động Spring, bạn sẽ gặp lỗi ở trên. Để ngăn chặn nó, chỉ cần tuần tự hóa lớp được ánh xạ (phản ánh JSON cấp một) và bỏ qua các mối quan hệ lồng nhau với @JsonIgnoreProperties(value = {"state"}),@JsonIgnoreProperties(value = {"country"})@JsonIgnoreProperties(value = {"region"})

Điều này sẽ ngăn ngoại lệ Lazyload cùng với lỗi trên. Sử dụng mã dưới đây làm ví dụ và thay đổi các lớp mô hình của bạn.

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;
}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.