Нет сеанса во время сериализации ленивых объектов в Spring Boot 2 - PullRequest
0 голосов
/ 29 июня 2018

Я перевожу мой REST API Spring Boot с 1.5.4 на 2.0.3.

Это две мои сущности, хранилище для одной из них и контроллер для доступа к ним:

Parent.java

@Entity
@Table(name = "PARENT")
public class Parent implements Serializable {

    @Id
    @GeneratedValue
    @Column(name = "ID")
    private Long id;

    @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
    private List<Child> children;
}

Child.java

@Entity
@Table(name = "CHILD")
public class Child implements Serializable {

    @Id
    @GeneratedValue
    @Column(name = "ID")
    private Long id;

    @Column(name = "PARENT_ID")
    private Long parentId;

    @JsonIgnore
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "PARENT_ID")
    private Parent parent;

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

ParentRepository.java

public interface ParentRepository extends JpaRepository<Parent, Long> {

}

ParentController.java

@RestController
@RequestMapping("/parents")
public class ParentController {

    @Autowired
    private ParentRepository parentRepository;

    @RequestMapping(method = RequestMethod.GET)
    public List<Parent> getParents() {
        return parentRepository.findAll();
    }
}

Похоже, что в классах @RestController больше нет активного сеанса с

parentRepository.findAll().get(0).getChildren().get(0).getName();

теперь выбрасывает

LazyInitializationException: failed to lazily initialize a collection of role: com.mycompany.myapplication.entity.Parent.children, could not initialize proxy - no Session

Это можно исправить, установив аннотацию @Transactional для метода контроллера или класса контроллера.


Однако у меня проблема с лениво загруженной children.

Если я запускаю приведенный выше пример кода, даже с аннотацией @Transactional, я получаю то же исключение, но с вложенным

com.fasterxml.jackson.databind.JsonMappingException

Это связано с тем, что сериализация в JSON происходит вне контроллера, следовательно, вне активного сеанса.

Существует некрасивое исправление, считывающее некоторые данные из каждого child перед выходом из метода:

@RequestMapping(method = RequestMethod.GET)
public List<Parent> getParents() {
    List<Parent> parents = parentRepository.findAll();
    parents.stream()
        .flatMap(p -> p.getChildren().stream())
        .forEach(Child::getName);
    return parents;
}

Это работает, но ужасно уродливо и добавляет много шаблонного.

Другим решением было бы сопоставить все сущности с DTO, прежде чем возвращать их клиенту. Но это решение добавляет еще один слой в мое приложение, которое мне не нужно.


Есть ли способ убедиться, что во время автоматической сериализации сущностей существует активный сеанс?

1 Ответ

0 голосов
/ 29 июня 2018

Так дааа ...

Во время миграции я ранее установил

spring.jpa.open-in-view = false

потому что я увидел новое предупреждение об этом в журнале. Этот параметр удаляет активную сессию, которую я хотел, чтобы добавить помощь ...

Удаление этого параметра и использование значения по умолчанию (true) полностью устранили мою проблему.

...