Джексон запускает JPA Lazy Fetching при сериализацииJAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Джексон запускает JPA Lazy Fetching при сериализации

Сообщение Anonymous »

У нас есть внутренний компонент, который раскрывает данные базы данных (postgresql) через JPA для Restful API. < /p>

Проблема в том, что при отправке объекта JPA в качестве ответа REST я могу видеть запуска Jackson All Lazy JPA. (Упрощено): < /p>

Код: Выделить всё

import org.springframework.hateoas.ResourceSupport;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Entity
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")//for resolving this bidirectional relationship, otherwise StackOverFlow due to infinite recursion
public class Parent extends ResourceSupport implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue
private Long id;

//we actually use Set and override hashcode&equals
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
private List children = new ArrayList();

@Transactional
public void addChild(Child child) {

child.setParent(this);
children.add(child);
}

@Transactional
public void removeChild(Child child) {

child.setParent(null);
children.remove(child);
}

public Long getId() {

return id;
}

@Transactional
public List getReadOnlyChildren() {

return Collections.unmodifiableList(children);
}
}
< /code>

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import java.io.Serializable;

@Entity
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class Child implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue
private Long id;

@ManyToOne
@JoinColumn(name = "id")
private Parent parent;

public Long getId() {

return id;
}

public Parent getParent() {

return parent;
}

/**
* Only for usage in {@link Parent}
*/
void setParent(final Parent parent) {

this.parent = parent;
}
}
< /code>

import org.springframework.data.repository.CrudRepository;

public interface ParentRepository extends CrudRepository {}
< /code>

import com.avaya.adw.db.repo.ParentRepository;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.hateoas.Link;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;

@RestController
@RequestMapping("/api/v1.0/parents")
public class ParentController {

private final String hostPath;

private final ParentRepository parentRepository;

public ParentController(@Value("${app.hostPath}") final String hostPath,
final ParentRepository parentRepository) {

// in application.properties: app.hostPath=/api/v1.0/
this.hostPath = hostPath;
this.parentRepository = parentRepository;
}

@CrossOrigin(origins = "*")
@GetMapping("/{id}")
public ResponseEntity  getParent(@PathVariable(value = "id") long id) {

final Parent parent = parentRepository.findOne(id);
if (parent == null) {
return new ResponseEntity(new HttpHeaders(), HttpStatus.NOT_FOUND);
}
Link selfLink = linkTo(Parent.class)
.slash(hostPath + "parents")
.slash(parent.getId()).withRel("self");
Link updateLink = linkTo(Parent.class)
.slash(hostPath + "parents")
.slash(parent.getId()).withRel("update");
Link deleteLink = linkTo(Parent.class)
.slash(hostPath + "parents")
.slash(parent.getId()).withRel("delete");
Link syncLink = linkTo(Parent.class)
.slash(hostPath + "parents")
.slash(parent.getId())
.slash("sync").withRel("sync");
parent.add(selfLink);
parent.add(updateLink);
parent.add(deleteLink);
parent.add(syncLink);
return new ResponseEntity(adDataSource, new HttpHeaders(), HttpStatus.OK);
}
}
< /code>



Итак, если я отправлю get ... /api /v1.0 /pary /1 < /code>, ответ состоит из следующего: < /p>

{
"id": 1,
"children": [
{
"id": 1,
"parent": 1
},
{
"id": 2,
"parent": 1
},
{
"id": 3,
"parent": 1
}
],
"links": [
{
"rel": "self",
"href": "http://.../api/v1.0/parents/1"
},
{
"rel": "update",
"href": "http://.../api/v1.0/parents/1"
},
{
"rel": "delete",
"href": "http://.../api/v1.0/parents/1"
},
{
"rel": "sync",
"href": "http://.../api/v1.0/parents/1/sync"
}
]
}
< /code>

Но я ожидаю, что он не содержит детей < /code> или содержит его в виде пустого массива или нулевого - чтобы не приносить фактические значения из базы данных. < /p>



У компонента есть следующая заметная Maven bootendy: < /p>

- Br />
- Br />
- Br />
   - Br />
. 1.5.7.Release
- Spring Boot Starter Web 1.5.7.Release (версия от родителя)
- Spring Hateoas 0.23.0.Release
- Джексон Databind 2.8.8 (это 2,8,1 в веб -стартере, я не знаю, почему мы переопределяем это)
- Spring Boot Data JPA 1.5.7. 5.0.12.final
< /pre>



 пробовал до сих пор < /h1>

Отладка показала, что есть один выбор < /code> on parent < /code> at parentRepository.findone (id) < /код> и другой на родительском языке. Serialization. < /p>

Сначала я попытался применить @jsonignore < /code> к ленивым коллекциям, но это игнорирует коллекцию, даже если она на самом деле содержит что-то (уже было извлечено). < /p>

Я обнаружил о проекте Jackson-datatype-hibernate, который утверждает < /p> chlockequequequeque-hibernate, который < /p> chlockequequequeque-hibernate, который утверждает < /p> chlockequequequeque-hibernate. />  Создайте модуль Jackson (JAR) для поддержки сериализации JSON и
Deserialization Hibernate (http://hibernate.org) специфических данных данных
и свойств; [b] Особенно аспекты ленивого загрузки [/b].


Идея об этом состоит в том, чтобы зарегистрировать hibernate5module 
(если версия 5 Hibernate используется) для CodateMapper и то, что это должно сделать, как модуль, настройка, настройка, настройка, настройка. По умолчанию. И погуглил способ включить его в Spring Boot (я также нашел другие источники, но они в основном ссылаются на это). < /P>



1. Прямо odd Module < /strong> (Spring Boot Special): < /p>

Код: Выделить всё

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

@Configuration
public class HibernateConfiguration {

@Bean
public Module disableForceLazyFetching() {

return new Hibernate5Module();
}
}
отладка показала, что ObjectMapper вызывается пружиной, когда он возвращает Parent содержит этот модуль и имеет настройки Lazy, установленную False, как и ожидалось. Но тогда он все еще получает детей .

Дальнейшая отладка показала: com.fasterxml.jackson.databind.ser.std.beanserializerbase.serializefields итерации через свойства (

Код: Выделить всё

com.fasterxml.jackson.databind.ser.BeanPropertyWriter
) и вызывает их метод serializeasfield , где первая строка: final value объекта = (_accessormethod == null)? _field.get (bean): _accessormethod.invoke (bean); , что запускает ленивую загрузку. Я не смог бы заметить ни одного места, где код будет фактически заботиться об этом модуле Hibernate.

upd [/b] также попытался включить serialize_identifier_for_lazy_not_loaded_objects , который должен включать фактический идентификатор ленивого свойства, а не Null (который является обязательным).@Bean
public Module disableForceLazyFetching() {

Hibernate5Module module = new Hibernate5Module();
module.enable(Hibernate5Module.Feature.SERIALIZE_IDENTIFIER_FOR_LAZY_NOT_LOADED_OBJECTS);

return module;
}
< /code>

Отладка показала, что опция включена, но это все еще не имело эффекта. < /p>



2. Инструктировать Spring MVC добавить модуль < /strong>:
< /p>

import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import java.util.List;

@Configuration
@EnableWebMvc
public class HibernateConfiguration extends WebMvcConfigurerAdapter {

@Override
public void configureMessageConverters(List

Подробнее здесь: https://stackoverflow.com/questions/479 ... ialization
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Джексон запускает JPA Lazy Fetching при сериализации
    Anonymous » » в форуме JAVA
    0 Ответы
    3 Просмотры
    Последнее сообщение Anonymous
  • Имеет проблемы с получением EF Core 8 Lazy Lazy Roading после обновления в базу данных
    Anonymous » » в форуме C#
    0 Ответы
    2 Просмотры
    Последнее сообщение Anonymous
  • Имеет проблемы с получением EF Core 8 Lazy Lazy Roading после обновления в базу данных
    Anonymous » » в форуме C#
    0 Ответы
    1 Просмотры
    Последнее сообщение Anonymous
  • Java Spring HttpMessageNotWritableException/JsonMappingException с Hibernate FetchType.LAZY в процессе сериализации Джек
    Anonymous » » в форуме JAVA
    0 Ответы
    24 Просмотры
    Последнее сообщение Anonymous
  • В этом выпуске он запускает драйвер Chrome, но не запускает веб-страницу.
    Anonymous » » в форуме JAVA
    0 Ответы
    131 Просмотры
    Последнее сообщение Anonymous

Вернуться в «JAVA»