Spring Boot 2. Джексон json-сериализация или Spring Data JPA FetchType.Lazy - PullRequest
0 голосов
/ 29 мая 2018

Мой случай очень странный, и, честно говоря, я не совсем уверен, если это проблема сериализации Джексона или что-то связанное с Spring Data JPA о том, как он выбирает объекты Lazy

Spring 2.0.2

  • spring-boot-starter-data-jpa
  • spring-boot-starter-web
  • spring-boot-devtools
  • mysql-connector-java

При поиске большинства людей проблема с Джексоном заключается в том, что при сериализации ленивая выборка за пределами сеанса вызывает исключение ниже. Однако , я вообще не получаю это исключение ....

org.hibernate.LazyInitializationException: не удалось инициализировать прокси - нет сеанса

Проблема

  1. Фактически получает данные и возвращает объект json в мой контроллер (запрос гибернации ниже).Это проблема для извлечения Eagerly, потому что он получает ненужные большие данные, которые не используются.

Структура (Пропустите метод получения и установки, чтобы сделать поток короче)

       User
        | <---[ OneToMany ]        
     Employee { hierarchies entity }
        |
  +-----+-----+
  |           |
PartTime   FullTime

Пользователь

@Entity
public class User {

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

@OneToMany(mappedBy="user")
@JsonIgnoreProperties("user")
private List<Employee> employee = new ArrayList<>();

Empolyee

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Employee {

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

@ManyToOne
@JsonIgnoreProperties("employee")
private User user;

FullTime / PartTime (изменение заработной платы поля на hourelywage при работе в PartTime)

@Entity
public class FullTime extends Employee  {

private BigDecimal salary;

UserRepository расширяет CrudRepository

UserService

public User getUserById(Long id) {

    Optional<User> optionalUser = userRepo.findById(id);
    User user = optionalUser.get();

    logger.info("\n User -> {}", user);
    return user;
}

Контроллер

@RestController
@RequestMapping(value="/api/user")
public class UserController {

  @GetMapping(value="/{userId}" )
  public User getUser(@PathVariable("userId") Long id) {
    return userService.getUserById(id);
  }   

}

В моем приложении установлен CommandLineRunner, который позволяет мне запускать команды при запуске приложения

@Override
public void run(String... args) throws Exception {
  logger.info("users 1 -> {}" , userService.getUserById(1L));
}


Hibernate: 
select
    user0_.id as id1_3_0_,
    user0_.name as name2_3_0_ 
from
    user user0_ 
where
    user0_.id=?

INFO 14434 --- [  restartedMain] ication$$EnhancerBySpringCGLIB$$6cf0457c :     
users 1 -> 
User [id=1, name=Jack]

Но когдаЯ прохожу свой контроллер http://localhost:8080/api/user/1 Я получаю 2 отдельных вызова гибернации, оба, кажется, находятся на моем уровне обслуживания.Имейте в виду, мой уровень обслуживания у меня нет Transactional, так что это действительно странно ....

Hibernate:  << 1st
select
    user0_.id as id1_3_0_,
    user0_.name as name2_3_0_ 
from
    user user0_ 
where
    user0_.id=?

com.example.app.service.UserService      : << -- In service 
User -> 
User [id=1, name=Jack]

Hibernate: 
select
    employee0_.user_id as user_id2_0_0_,
    employee0_.id as id1_0_0_,
    employee0_.id as id1_0_1_,
    employee0_.user_id as user_id2_0_1_,
    employee0_1_.salary as salary1_1_1_,
    employee0_2_.hourly_wage as hourly_w1_2_1_,
    case 
        when employee0_1_.id is not null then 1 
        when employee0_2_.id is not null then 2 
        when employee0_.id is not null then 0 
    end as clazz_1_ 
from
    employee employee0_ 
left outer join
    full_time employee0_1_ 
        on employee0_.id=employee0_1_.id 
left outer join
    part_time employee0_2_ 
        on employee0_.id=employee0_2_.id 
where
    employee0_.user_id=?

Теперь, если это проблема с сериализацией Джексона, я посетил Избегайте сериализации Джексона на невнятых ленивыхobjects , Настроить Джексона для исключения атрибутов отложенной загрузки в Spring Boot и многого другого, но все это сделано путем расширения WebMvcConfigurerAdapter, который, как мне кажется, в spring5 устарел?

Если что-то не такделать с Spring Data JPA ... тогда, пожалуйста, пролите немного света, потому что я всегда думал, что вам нужна аннотация @Transaction для отложенного извлечения, чтобы связать отношения с сеансом гибернации ...

Извините за длинный поток ...

1 Ответ

0 голосов
/ 06 ноября 2018

Я думаю, что у вас включено свойство spring.jpa.open-in-view (по умолчанию true).Проверьте, нет ли в вашем журнале следующего сообщения:

spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning

Вы должны увидеть требуемое исключение, если отключите его.

...