杰克逊如何在转换之外序列化对象

时间:2018-05-31 07:36:05

标签: spring-boot jackson

这对我来说有点奇怪。我的理解是,如果你尝试访问Hibernate会话之外的实体,你应该得到一个LazyInitializationException - 没有会话,但我没有得到这个异常。事实上,似乎我仍然在我的服务层之外的会话中继续使用@Transactional注释。

问题

  • 这是应该的样子吗?或者有些东西我没有正确设置?

结构

       User
        | 
     Profile { hierarchies entity }
        |
  +-----+-----+
  |           |
Teacher   Student

用户

@Entity
@Table(name="user")
public class User {

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

 @OneToMany(fetch = FetchType.LAZY , mappedBy = "user")
 @JsonManagedReference
 @JsonInclude(JsonInclude.Include.NON_EMPTY)
 private List<Profile> profiles = new ArrayList<>();

服务

@Override
@Transactional
public User getUserById(Long id) {

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

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

Controller :: 而不是thow Exception,或者应该返回空数组。 Hibernate执行左连接

@GetMapping(value="/{userId}", produces=MediaType.APPLICATION_JSON_UTF8_VALUE)
public User getUser(@PathVariable("userId") Long userId) {

    logger.info("User Controller is called");

    User user = userService.getUserById(userId);

    logger.info("User is returned -> {}", user);

    logger.info("Profiles -> {}", user.getProfiles());  // <-- Expecting this to throw LazyInitializationException

    return user;
}

控制台

    018-05-31 15:17:35.462  INFO 15599 --- [nio-8080-exec-1] c.d.c.controller.UserController          : User Controller is called
Hibernate: 
    select
        user0_.id as id1_4_0_,
        user0_.firstname as firstnam2_4_0_,
        user0_.lastname as lastname3_4_0_ 
    from
        user user0_ 
    where
        user0_.id=?
2018-05-31 15:17:35.467  INFO 15599 --- [nio-8080-exec-1] c.d.c.services.UserServiceImpl           : 
 User -> 
User [id=1, firstname=Hendric, lastname=Rosenberg]
2018-05-31 15:17:35.467  INFO 15599 --- [nio-8080-exec-1] c.d.c.controller.UserController          : User is returned -> 
User [id=1, firstname=Hendric, lastname=Rosenberg]
Hibernate: 
    select
        profiles0_.user_id as user_id2_3_0_,
        profiles0_.id as id1_3_0_,
        profiles0_.id as id1_3_1_,
        profiles0_.user_id as user_id2_3_1_,
        profiles0_1_.citizent_id as citizent1_2_1_,
        profiles0_1_.profile_type as profile_2_2_1_,
        profiles0_2_.license as license1_1_1_,
        profiles0_2_.practitioner_type as practiti2_1_1_,
        profiles0_2_.profile_type as profile_3_1_1_,
        profiles0_2_.specialized as speciali4_1_1_,
        case 
            when profiles0_1_.id is not null then 1 
            when profiles0_2_.id is not null then 2 
            when profiles0_.id is not null then 0 
        end as clazz_1_ 
    from
        profile profiles0_ 
    left outer join
        patient profiles0_1_ 
            on profiles0_.id=profiles0_1_.id 
    left outer join
        medical_profession profiles0_2_ 
            on profiles0_.id=profiles0_2_.id 
    where
        profiles0_.user_id=?
c.d.c.controller.UserController          : User is returned -> [
 Student [profileType=STUDENT, id=A1236578889], 
 Teacher [profileType=TEACHER, license=234SFLLWEKD32342]]

1 个答案:

答案 0 :(得分:1)

spring.jpa.open-in-view = true默认设置。所以你不会得到一个LazyInitializationException

此属性将注册OpenEntityManagerInViewInterceptor

  

Spring Web请求拦截器,它将JPA EntityManager绑定到线程以进行整个请求处理。用于“Open EntityManager in View”模式,即允许在Web视图中进行延迟加载,尽管原始事务已经完成。   此拦截器通过当前线程使JPA EntityManagers可用,该线程将由事务管理器自动检测。它适用于通过JpaTransactionManager或JtaTransactionManager进行的服务层事务以及非事务性只读执行。   与OpenEntityManagerInViewFilter相比,此拦截器在Spring应用程序上下文中设置,因此可以利用bean连接。