Я работаю над 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
Я использую Spring Boot v1.3 с Hibernate 4.3
Теперь он сериализует весь объект и вложенные объекты.
РЕДАКТИРОВАТЬ: 2018
Поскольку это все еще получает комментарии, я уточню здесь. Это абсолютно только скрывает ошибку. Последствия для производительности есть. В то время мне нужно было что-то доставить и поработать над этим позже (что я и сделал, перестав использовать Spring). Так что да, послушайте кого-нибудь еще, если вы действительно хотите решить проблему. Если вы просто хотите, чтобы он ушел, используйте этот ответ. Это ужасная идея, но, черт возьми, может сработать для вас. Для справки, после этого больше никогда не возникало сбоев или проблем. Но, вероятно, это источник того, что в конечном итоге стало кошмаром производительности SQL.
источник
"handler":{},"hibernateLazyInitializer":{}
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
Как правильно предложено в предыдущих ответах, ленивая загрузка означает, что при извлечении объекта из базы данных вложенные объекты не извлекаются (и могут быть извлечены позже, когда это необходимо).
Теперь Джексон пытается сериализовать вложенный объект (== сделать из него JSON), но терпит неудачу, поскольку находит JavassistLazyInitializer вместо обычного объекта. Это ошибка, которую вы видите. Теперь, как это решить?
Как было предложено ранее CP510, один из вариантов - подавить ошибку с помощью этой строки конфигурации:
spring.jackson.serialization.fail-on-empty-beans=false
Но это связано с симптомами, а не с причиной . Чтобы решить ее элегантно, вам нужно решить, нужен ли вам этот объект в JSON или нет?
Если вам нужен объект в JSON, удалите
FetchType.LAZY
параметр из поля, которое его вызывает (это также может быть поле в каком-то вложенном объекте, а не только в корневом объекте, который вы извлекаете).Если объект в JSON не нужен, аннотируйте получатель этого поля (или само поле, если вам тоже не нужно принимать входящие значения)
@JsonIgnore
, например:// this field will not be serialized to/from JSON @JsonIgnore private NestedType secret;
Если у вас есть более сложные потребности (например , различные правила для различных контроллеров REST , используя один и тот же объект), вы можете использовать Джексон взгляды или фильтрацию или для очень простого случая использования, принесите вложенные объекты отдельно.
источник
RangeError: Maximum call stack size exceeded
Вы можете использовать дополнительный модуль для Jackson, который обрабатывает отложенную загрузку Hibernate.
Дополнительная информация на 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);
источник
Добавьте эту аннотацию к классу сущности (модели), которая работает для меня, это вызывает ленивую загрузку через прокси-объект спящего режима.
источник
Это исключение
получаю, потому что, я надеюсь, вы отправляете ответ как объект Serializable.
Это проблема, возникающая весной. Чтобы решить эту проблему, отправьте объект 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
В контроллере преобразуйте серилизуемые поля объекта в поля класса 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 и выше вы можете удалить прокси-сервер гибернации, как показано ниже, он предоставит вам фактический объект, чтобы вы могли правильно его сериализовать:
Object unproxiedEntity = Hibernate.unproxy( proxy );
источник
Hibernate.initialize
заранее.Для Hibernate вы можете использовать проект jackson-datatype-hibernate, чтобы обеспечить сериализацию / десериализацию 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; } }
источник
can't parse JSON. Raw result:
. Любая помощь?Решение основано на приведенном ниже решении @marco. Я также обновил его ответ этими данными.
Проблема здесь в отложенной загрузке подобъектов, когда Джексон находит только прокси-серверы гибернации, а не полноценные объекты.
Таким образом, у нас остается два варианта: подавить исключение, как это сделано выше в ответе, за который проголосовали большинство здесь, или убедиться, что объекты LazyLoad загружены.
Если вы выберете последний вариант, решение будет заключаться в использовании библиотеки jackson-datatype и настройке библиотеки на инициализацию зависимостей отложенной загрузки до сериализации.
Для этого я добавил новый класс конфигурации.
@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-компонентов.@Bean
как обычно.module.enable(Hibernate5Module.Feature.FORCE_LAZY_LOADING);
- включить отложенную загрузку зависимостей.Внимание - обратите внимание на его влияние на производительность. иногда EAGER fetch помогает, но даже если вы сделаете это с нетерпением, вам все равно понадобится этот код, потому что прокси-объекты все еще существуют для всех других сопоставлений, кроме
@OneToOne
PS: В качестве общего комментария я бы не одобрил практику отправки всего объекта данных обратно в ответ Json. Для этого следует использовать Dto и использовать какой-нибудь картограф, например mapstruct, для их сопоставления. Это избавит вас от случайных лазеек в системе безопасности, а также от вышеуказанного исключения.
источник
У меня сейчас такая же проблема. проверьте, исправляете ли вы выборку в ленивом режиме с помощью @jsonIQgnore
@ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="teachers") @JsonIgnoreProperties("course") Teacher teach;
Просто удалите «(fetch = ...)» или аннотацию «@jsonIgnore», и все заработает.
@ManyToOne @JoinColumn(name="teachers") @JsonIgnoreProperties("course") Teacher teach;
источник
Или вы можете настроить mapper как:
// настраиваемая конфигурация для отложенной загрузки
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);
источник
Возможно, проблема связана с вашими отношениями сущностей Hibernate ... просто прекратите ленивую загрузку этой связанной сущности ... например ... Я решил ниже, установив lazy = "false" для 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>
источник
Я изменил (в классе модели аннотации)
к
и сработало красиво ...
Любить это.
источник
fetch
стратегии модели имеет несколько последствий для производительности. С этим изменением вы получаете гораздо больше данных из базы данных. Это может быть правильное решение, но сначала необходимо исследование производительности.Это проблема с Джексоном. Чтобы предотвратить это, проинструктируйте Джексона не сериализовать вложенную связь или вложенный класс.
Взгляните на следующий пример. Класс адреса сопоставлен с классами City , State и Country, а сам State указывает на Country, а Country указывает на Region. Когда вы получите значения адреса через Spring boot REST API, вы получите указанную выше ошибку. Чтобы предотвратить это, просто сериализуйте сопоставленный класс (который отражает JSON первого уровня) и игнорируйте вложенные отношения с
@JsonIgnoreProperties(value = {"state"})
,@JsonIgnoreProperties(value = {"country"})
и@JsonIgnoreProperties(value = {"region"})
Это предотвратит исключение Lazyload вместе с указанной выше ошибкой. Используйте приведенный ниже код в качестве примера и измените классы вашей модели.
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; }
источник
@JsonIgnoreProperties ({"hibernateLazyInitializer", "handler"})
меня устраивает
источник
Пытаться
implements interface Serializable
источник